new framwork
This commit is contained in:
121
client/src/pages/api/user/checkPayResult.ts
Normal file
121
client/src/pages/api/user/checkPayResult.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase, User, Pay, TrainingData } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { PaySchema, UserModelSchema } from '@/types/mongoSchema';
|
||||
import dayjs from 'dayjs';
|
||||
import { getPayResult } from '@/service/utils/wxpay';
|
||||
import { pushPromotionRecord } from '@/service/utils/promotion';
|
||||
import { PRICE_SCALE } from '@/constants/common';
|
||||
import { startQueue } from '@/service/utils/tools';
|
||||
|
||||
/* 校验支付结果 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
let { payId } = req.query as { payId: string };
|
||||
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
// 查找订单记录校验
|
||||
const payOrder = await Pay.findById<PaySchema>(payId);
|
||||
|
||||
if (!payOrder) {
|
||||
throw new Error('订单不存在');
|
||||
}
|
||||
if (payOrder.status !== 'NOTPAY') {
|
||||
throw new Error('订单已结算');
|
||||
}
|
||||
|
||||
// 获取当前用户
|
||||
const user = await User.findById(userId);
|
||||
if (!user) {
|
||||
throw new Error('找不到用户');
|
||||
}
|
||||
// 获取邀请者
|
||||
let inviter: UserModelSchema | null = null;
|
||||
if (user.inviterId) {
|
||||
inviter = await User.findById(user.inviterId);
|
||||
}
|
||||
|
||||
const payRes = await getPayResult(payOrder.orderId);
|
||||
|
||||
// 校验下是否超过一天
|
||||
const orderTime = dayjs(payOrder.createTime);
|
||||
const diffInHours = dayjs().diff(orderTime, 'hours');
|
||||
|
||||
if (payRes.trade_state === 'SUCCESS') {
|
||||
// 订单已支付
|
||||
try {
|
||||
// 更新订单状态. 如果没有合适的订单,说明订单重复了
|
||||
const updateRes = await Pay.updateOne(
|
||||
{
|
||||
_id: payId,
|
||||
status: 'NOTPAY'
|
||||
},
|
||||
{
|
||||
status: 'SUCCESS'
|
||||
}
|
||||
);
|
||||
if (updateRes.modifiedCount === 1) {
|
||||
// 给用户账号充钱
|
||||
await User.findByIdAndUpdate(userId, {
|
||||
$inc: { balance: payOrder.price }
|
||||
});
|
||||
// 推广佣金发放
|
||||
if (inviter) {
|
||||
pushPromotionRecord({
|
||||
userId: inviter._id,
|
||||
objUId: userId,
|
||||
type: 'invite',
|
||||
// amount 单位为元,需要除以缩放比例,最后乘比例
|
||||
amount: (payOrder.price / PRICE_SCALE) * inviter.promotion.rate * 0.01
|
||||
});
|
||||
}
|
||||
jsonRes(res, {
|
||||
data: '支付成功'
|
||||
});
|
||||
unlockTask(userId);
|
||||
}
|
||||
} catch (error) {
|
||||
await Pay.findByIdAndUpdate(payId, {
|
||||
status: 'NOTPAY'
|
||||
});
|
||||
console.log(error);
|
||||
}
|
||||
} else if (payRes.trade_state === 'CLOSED' || diffInHours > 24) {
|
||||
// 订单已关闭
|
||||
await Pay.findByIdAndUpdate(payId, {
|
||||
status: 'CLOSED'
|
||||
});
|
||||
jsonRes(res, {
|
||||
data: '订单已过期'
|
||||
});
|
||||
} else {
|
||||
throw new Error(payRes?.trade_state_desc || '订单无效');
|
||||
}
|
||||
} catch (err) {
|
||||
// console.log(err);
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function unlockTask(userId: string) {
|
||||
try {
|
||||
await TrainingData.updateMany(
|
||||
{
|
||||
userId
|
||||
},
|
||||
{
|
||||
lockTime: new Date('2000/1/1')
|
||||
}
|
||||
);
|
||||
startQueue();
|
||||
} catch (error) {
|
||||
unlockTask(userId);
|
||||
}
|
||||
}
|
||||
49
client/src/pages/api/user/getBill.ts
Normal file
49
client/src/pages/api/user/getBill.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase, Bill } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { adaptBill } from '@/utils/adapt';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
let { pageNum = 1, pageSize = 10 } = req.query as {
|
||||
pageNum: string;
|
||||
pageSize: string;
|
||||
};
|
||||
|
||||
pageNum = +pageNum;
|
||||
pageSize = +pageSize;
|
||||
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
const where = {
|
||||
userId
|
||||
};
|
||||
|
||||
// get bill record and total by record
|
||||
const [bills, total] = await Promise.all([
|
||||
Bill.find(where)
|
||||
.sort({ time: -1 }) // 按照创建时间倒序排列
|
||||
.skip((pageNum - 1) * pageSize)
|
||||
.limit(pageSize),
|
||||
Bill.countDocuments(where)
|
||||
]);
|
||||
|
||||
jsonRes(res, {
|
||||
data: {
|
||||
pageNum,
|
||||
pageSize,
|
||||
data: bills.map(adaptBill),
|
||||
total
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
43
client/src/pages/api/user/getPayCode.ts
Normal file
43
client/src/pages/api/user/getPayCode.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
import { connectToDatabase, Pay } from '@/service/mongo';
|
||||
import { PRICE_SCALE } from '@/constants/common';
|
||||
import { nativePay } from '@/service/utils/wxpay';
|
||||
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 20);
|
||||
|
||||
/* 获取支付二维码 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
let { amount = 0 } = req.query as { amount: string };
|
||||
amount = +amount;
|
||||
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
const id = nanoid();
|
||||
await connectToDatabase();
|
||||
|
||||
const code_url = await nativePay(amount * 100, id);
|
||||
|
||||
// 充值记录 + 1
|
||||
const payOrder = await Pay.create({
|
||||
userId,
|
||||
price: amount * PRICE_SCALE,
|
||||
orderId: id
|
||||
});
|
||||
|
||||
jsonRes(res, {
|
||||
data: {
|
||||
payId: payOrder._id,
|
||||
codeUrl: code_url
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
27
client/src/pages/api/user/getPayOrders.ts
Normal file
27
client/src/pages/api/user/getPayOrders.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { connectToDatabase, Pay } from '@/service/mongo';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
const records = await Pay.find({
|
||||
userId,
|
||||
status: { $ne: 'CLOSED' }
|
||||
}).sort({ createTime: -1 });
|
||||
|
||||
jsonRes(res, {
|
||||
data: records
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
31
client/src/pages/api/user/inform/countUnread.ts
Normal file
31
client/src/pages/api/user/inform/countUnread.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase, Inform } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
if (!req.headers.cookie) {
|
||||
return jsonRes(res, {
|
||||
data: 0
|
||||
});
|
||||
}
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
const data = await Inform.countDocuments({
|
||||
userId,
|
||||
read: false
|
||||
});
|
||||
|
||||
jsonRes(res, {
|
||||
data
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
data: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
40
client/src/pages/api/user/inform/list.ts
Normal file
40
client/src/pages/api/user/inform/list.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase, Inform } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
const { pageNum, pageSize = 10 } = req.body as {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
const [informs, total] = await Promise.all([
|
||||
Inform.find({ userId })
|
||||
.sort({ time: -1 }) // 按照创建时间倒序排列
|
||||
.skip((pageNum - 1) * pageSize)
|
||||
.limit(pageSize),
|
||||
Inform.countDocuments({ userId })
|
||||
]);
|
||||
|
||||
jsonRes(res, {
|
||||
data: {
|
||||
pageNum,
|
||||
pageSize,
|
||||
data: informs,
|
||||
total
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
29
client/src/pages/api/user/inform/read.ts
Normal file
29
client/src/pages/api/user/inform/read.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase, Inform } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
const { id } = req.query as { id: string };
|
||||
|
||||
await Inform.findOneAndUpdate(
|
||||
{
|
||||
_id: id,
|
||||
userId
|
||||
},
|
||||
{
|
||||
read: true
|
||||
}
|
||||
);
|
||||
|
||||
jsonRes(res);
|
||||
} catch (err) {
|
||||
jsonRes(res);
|
||||
}
|
||||
}
|
||||
75
client/src/pages/api/user/inform/send.ts
Normal file
75
client/src/pages/api/user/inform/send.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase, Inform, User } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { InformTypeEnum } from '@/constants/user';
|
||||
|
||||
export type Props = {
|
||||
type: `${InformTypeEnum}`;
|
||||
title: string;
|
||||
content: string;
|
||||
userId?: string;
|
||||
};
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await authUser({ req, authRoot: true });
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
jsonRes(res, {
|
||||
data: await sendInform(req.body),
|
||||
message: '发送通知成功'
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function sendInform({ type, title, content, userId }: Props) {
|
||||
if (!type || !title || !content) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (userId) {
|
||||
// skip it if have same inform within 5 minutes
|
||||
const inform = await Inform.findOne({
|
||||
type,
|
||||
title,
|
||||
content,
|
||||
userId,
|
||||
read: false,
|
||||
time: { $lte: new Date(Date.now() + 5 * 60 * 1000) }
|
||||
});
|
||||
|
||||
if (inform) return;
|
||||
|
||||
await Inform.create({
|
||||
type,
|
||||
title,
|
||||
content,
|
||||
userId
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// send to all user
|
||||
const users = await User.find({}, '_id');
|
||||
await Inform.insertMany(
|
||||
users.map(({ _id }) => ({
|
||||
type,
|
||||
title,
|
||||
content,
|
||||
userId: _id
|
||||
}))
|
||||
);
|
||||
} catch (error) {
|
||||
console.log('send inform error', error);
|
||||
}
|
||||
}
|
||||
48
client/src/pages/api/user/loginByPassword.ts
Normal file
48
client/src/pages/api/user/loginByPassword.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { User } from '@/service/models/user';
|
||||
import { setCookie } from '@/service/utils/tools';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
const { username, password } = req.body;
|
||||
|
||||
if (!username || !password) {
|
||||
throw new Error('缺少参数');
|
||||
}
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
// 检测用户是否存在
|
||||
const authUser = await User.findOne({
|
||||
username
|
||||
});
|
||||
if (!authUser) {
|
||||
throw new Error('用户未注册');
|
||||
}
|
||||
|
||||
const user = await User.findOne({
|
||||
username,
|
||||
password
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new Error('密码错误');
|
||||
}
|
||||
|
||||
setCookie(res, user._id);
|
||||
|
||||
jsonRes(res, {
|
||||
data: {
|
||||
user
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
16
client/src/pages/api/user/loginout.ts
Normal file
16
client/src/pages/api/user/loginout.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { clearCookie } from '@/service/utils/tools';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
clearCookie(res);
|
||||
jsonRes(res);
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
69
client/src/pages/api/user/promotion/getPromotionData.ts
Normal file
69
client/src/pages/api/user/promotion/getPromotionData.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase, User, promotionRecord } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import mongoose from 'mongoose';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
const invitedAmount = await User.countDocuments({
|
||||
inviterId: userId
|
||||
});
|
||||
|
||||
// 计算累计合
|
||||
const countHistory: { totalAmount: number }[] = await promotionRecord.aggregate([
|
||||
{
|
||||
$match: {
|
||||
userId: new mongoose.Types.ObjectId(userId),
|
||||
amount: { $gt: 0 }
|
||||
}
|
||||
},
|
||||
{
|
||||
$group: {
|
||||
_id: null, // 分组条件,这里使用 null 表示不分组
|
||||
totalAmount: { $sum: '$amount' } // 计算 amount 字段的总和
|
||||
}
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
_id: false, // 排除 _id 字段
|
||||
totalAmount: true // 只返回 totalAmount 字段
|
||||
}
|
||||
}
|
||||
]);
|
||||
// 计算剩余金额
|
||||
const countResidue: { totalAmount: number }[] = await promotionRecord.aggregate([
|
||||
{ $match: { userId: new mongoose.Types.ObjectId(userId) } },
|
||||
{
|
||||
$group: {
|
||||
_id: null, // 分组条件,这里使用 null 表示不分组
|
||||
totalAmount: { $sum: '$amount' } // 计算 amount 字段的总和
|
||||
}
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
_id: false, // 排除 _id 字段
|
||||
totalAmount: true // 只返回 totalAmount 字段
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
jsonRes(res, {
|
||||
data: {
|
||||
invitedAmount,
|
||||
historyAmount: countHistory[0]?.totalAmount || 0,
|
||||
residueAmount: countResidue[0]?.totalAmount || 0
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
47
client/src/pages/api/user/promotion/getPromotions.ts
Normal file
47
client/src/pages/api/user/promotion/getPromotions.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase, promotionRecord } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
let { pageNum = 1, pageSize = 10 } = req.query as {
|
||||
pageNum: string;
|
||||
pageSize: string;
|
||||
};
|
||||
pageNum = +pageNum;
|
||||
pageSize = +pageSize;
|
||||
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
const data = await promotionRecord
|
||||
.find(
|
||||
{
|
||||
userId
|
||||
},
|
||||
'_id createTime type amount'
|
||||
)
|
||||
.sort({ _id: -1 })
|
||||
.skip((pageNum - 1) * pageSize)
|
||||
.limit(pageSize);
|
||||
|
||||
jsonRes(res, {
|
||||
data: {
|
||||
pageNum,
|
||||
pageSize,
|
||||
data,
|
||||
total: await promotionRecord.countDocuments({
|
||||
userId
|
||||
})
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
72
client/src/pages/api/user/register.ts
Normal file
72
client/src/pages/api/user/register.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { User } from '@/service/models/user';
|
||||
import { AuthCode } from '@/service/models/authCode';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { setCookie } from '@/service/utils/tools';
|
||||
import { UserAuthTypeEnum } from '@/constants/common';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
const { username, code, password, inviterId } = req.body;
|
||||
|
||||
if (!username || !code || !password) {
|
||||
throw new Error('缺少参数');
|
||||
}
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
// 验证码校验
|
||||
const authCode = await AuthCode.findOne({
|
||||
username,
|
||||
code,
|
||||
type: UserAuthTypeEnum.register,
|
||||
expiredTime: { $gte: Date.now() }
|
||||
});
|
||||
|
||||
if (!authCode) {
|
||||
throw new Error('验证码错误');
|
||||
}
|
||||
|
||||
// 重名校验
|
||||
const authRepeat = await User.findOne({
|
||||
username
|
||||
});
|
||||
|
||||
if (authRepeat) {
|
||||
throw new Error('该用户已被注册');
|
||||
}
|
||||
|
||||
const response = await User.create({
|
||||
username,
|
||||
password,
|
||||
inviterId: inviterId ? inviterId : undefined
|
||||
});
|
||||
|
||||
// 根据 id 获取用户信息
|
||||
const user = await User.findById(response._id);
|
||||
|
||||
if (!user) {
|
||||
throw new Error('获取用户信息异常');
|
||||
}
|
||||
|
||||
// 删除验证码记录
|
||||
await AuthCode.deleteMany({
|
||||
username
|
||||
});
|
||||
|
||||
setCookie(res, user._id);
|
||||
|
||||
jsonRes(res, {
|
||||
data: {
|
||||
user
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
71
client/src/pages/api/user/sendAuthCode.ts
Normal file
71
client/src/pages/api/user/sendAuthCode.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { AuthCode } from '@/service/models/authCode';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { sendPhoneCode, sendEmailCode } from '@/service/utils/sendNote';
|
||||
import { UserAuthTypeEnum } from '@/constants/common';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet('123456789', 6);
|
||||
import { authGoogleToken } from '@/utils/plugin/google';
|
||||
import requestIp from 'request-ip';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
const { username, type, googleToken } = req.body as {
|
||||
username: string;
|
||||
type: `${UserAuthTypeEnum}`;
|
||||
googleToken: string;
|
||||
};
|
||||
|
||||
if (!username || !type) {
|
||||
throw new Error('缺少参数');
|
||||
}
|
||||
|
||||
// google auth
|
||||
process.env.SERVICE_GOOGLE_VER_TOKEN &&
|
||||
(await authGoogleToken({
|
||||
secret: process.env.SERVICE_GOOGLE_VER_TOKEN,
|
||||
response: googleToken,
|
||||
remoteip: requestIp.getClientIp(req) || undefined
|
||||
}));
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
const code = nanoid();
|
||||
|
||||
// 判断 1 分钟内是否有重复数据
|
||||
const authCode = await AuthCode.findOne({
|
||||
username,
|
||||
type,
|
||||
expiredTime: { $gte: Date.now() + 4 * 60 * 1000 } // 如果有一个记录的过期时间,大于当前+4分钟,说明距离上次发送还没到1分钟。(因为默认创建时,过期时间是未来5分钟)
|
||||
});
|
||||
|
||||
if (authCode) {
|
||||
throw new Error('请勿频繁获取验证码');
|
||||
}
|
||||
|
||||
// 创建 auth 记录
|
||||
await AuthCode.create({
|
||||
username,
|
||||
type,
|
||||
code
|
||||
});
|
||||
|
||||
if (username.includes('@')) {
|
||||
await sendEmailCode(username, code, type);
|
||||
} else {
|
||||
// 发送验证码
|
||||
await sendPhoneCode(username, code);
|
||||
}
|
||||
|
||||
jsonRes(res, {
|
||||
message: '发送验证码成功'
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
30
client/src/pages/api/user/tokenLogin.ts
Normal file
30
client/src/pages/api/user/tokenLogin.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { User } from '@/service/models/user';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
// 根据 id 获取用户信息
|
||||
const user = await User.findById(userId);
|
||||
|
||||
if (!user) {
|
||||
throw new Error('账号异常');
|
||||
}
|
||||
|
||||
jsonRes(res, {
|
||||
data: user
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
35
client/src/pages/api/user/update.ts
Normal file
35
client/src/pages/api/user/update.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { User } from '@/service/models/user';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { UserUpdateParams } from '@/types/user';
|
||||
|
||||
/* 更新一些基本信息 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
const { openaiKey, avatar } = req.body as UserUpdateParams;
|
||||
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
await connectToDatabase();
|
||||
// 更新对应的记录
|
||||
await User.updateOne(
|
||||
{
|
||||
_id: userId
|
||||
},
|
||||
{
|
||||
...(avatar && { avatar }),
|
||||
...(openaiKey !== undefined && { openaiKey })
|
||||
}
|
||||
);
|
||||
|
||||
jsonRes(res);
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
64
client/src/pages/api/user/updatePasswordByCode.ts
Normal file
64
client/src/pages/api/user/updatePasswordByCode.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { User } from '@/service/models/user';
|
||||
import { AuthCode } from '@/service/models/authCode';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { UserAuthTypeEnum } from '@/constants/common';
|
||||
import { setCookie } from '@/service/utils/tools';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
const { username, code, password } = req.body;
|
||||
|
||||
if (!username || !code || !password) {
|
||||
throw new Error('缺少参数');
|
||||
}
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
// 验证码校验
|
||||
const authCode = await AuthCode.findOne({
|
||||
username,
|
||||
code,
|
||||
type: UserAuthTypeEnum.findPassword,
|
||||
expiredTime: { $gte: Date.now() }
|
||||
});
|
||||
|
||||
if (!authCode) {
|
||||
throw new Error('验证码错误');
|
||||
}
|
||||
|
||||
// 更新对应的记录
|
||||
await User.updateOne(
|
||||
{
|
||||
username
|
||||
},
|
||||
{
|
||||
password
|
||||
}
|
||||
);
|
||||
|
||||
// 根据 username 获取用户信息
|
||||
const user = await User.findOne({
|
||||
username
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new Error('获取用户信息异常');
|
||||
}
|
||||
|
||||
setCookie(res, user._id);
|
||||
|
||||
jsonRes(res, {
|
||||
data: {
|
||||
user
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user