mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 05:12:39 +00:00
perf: pay
This commit is contained in:
@@ -9,9 +9,6 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alicloud/dysmsapi20170525": "^2.0.23",
|
||||
"@alicloud/openapi-client": "^0.4.5",
|
||||
"@alicloud/tea-util": "^1.4.5",
|
||||
"@chakra-ui/icons": "^2.0.17",
|
||||
"@chakra-ui/react": "^2.7.0",
|
||||
"@chakra-ui/system": "^2.5.8",
|
||||
@@ -42,7 +39,6 @@
|
||||
"next": "13.1.6",
|
||||
"next-i18next": "^13.3.0",
|
||||
"nextjs-cors": "^2.1.2",
|
||||
"nodemailer": "^6.9.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"openai": "^3.3.0",
|
||||
"papaparse": "^5.4.1",
|
||||
@@ -62,7 +58,6 @@
|
||||
"request-ip": "^3.3.0",
|
||||
"sass": "^1.58.3",
|
||||
"tunnel": "^0.0.6",
|
||||
"wxpay-v3": "^3.0.2",
|
||||
"zustand": "^4.3.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -73,7 +68,6 @@
|
||||
"@types/jsonwebtoken": "^9.0.1",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"@types/node": "18.14.0",
|
||||
"@types/nodemailer": "^6.4.7",
|
||||
"@types/papaparse": "^5.3.7",
|
||||
"@types/pg": "^8.6.6",
|
||||
"@types/react": "18.0.28",
|
||||
|
1096
client/pnpm-lock.yaml
generated
1096
client/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,7 @@ const PayRecordTable = () => {
|
||||
const data = await checkPayResult(payId);
|
||||
toast({
|
||||
title: data,
|
||||
status: 'info'
|
||||
status: 'success'
|
||||
});
|
||||
const res = await getPayOrders();
|
||||
setPayOrders(res);
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase, User, Pay, TrainingData } from '@/service/mongo';
|
||||
import { User, Pay, TrainingData } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { PaySchema } from '@/types/mongoSchema';
|
||||
import dayjs from 'dayjs';
|
||||
import { getPayResult } from '@/service/utils/wxpay';
|
||||
import { startQueue } from '@/service/utils/tools';
|
||||
import { getWxPayQRResult } from '@/service/api/plugins';
|
||||
|
||||
/* 校验支付结果 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
@@ -14,8 +14,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
await connectToDatabase();
|
||||
|
||||
// 查找订单记录校验
|
||||
const payOrder = await Pay.findById<PaySchema>(payId);
|
||||
|
||||
@@ -32,11 +30,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
throw new Error('找不到用户');
|
||||
}
|
||||
|
||||
const payRes = await getPayResult(payOrder.orderId);
|
||||
|
||||
// 校验下是否超过一天
|
||||
const orderTime = dayjs(payOrder.createTime);
|
||||
const diffInHours = dayjs().diff(orderTime, 'hours');
|
||||
const payRes = await getWxPayQRResult(payOrder.orderId);
|
||||
|
||||
if (payRes.trade_state === 'SUCCESS') {
|
||||
// 订单已支付
|
||||
@@ -76,12 +70,18 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
data: '更新订单失败,请重试'
|
||||
});
|
||||
}
|
||||
|
||||
// 校验下是否超过一天
|
||||
const orderTime = dayjs(payOrder.createTime);
|
||||
const diffInHours = dayjs().diff(orderTime, 'hours');
|
||||
|
||||
if (payRes.trade_state === 'CLOSED' || diffInHours > 24) {
|
||||
// 订单已关闭
|
||||
await Pay.findByIdAndUpdate(payId, {
|
||||
status: 'CLOSED'
|
||||
});
|
||||
return jsonRes(res, {
|
||||
code: 500,
|
||||
data: '订单已过期'
|
||||
});
|
||||
}
|
||||
|
@@ -1,12 +1,9 @@
|
||||
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 { Pay } from '@/service/mongo';
|
||||
import { PRICE_SCALE } from '@/constants/common';
|
||||
import { nativePay } from '@/service/utils/wxpay';
|
||||
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 20);
|
||||
import { getWxPayQRUrl } from '@/service/api/plugins';
|
||||
|
||||
/* 获取支付二维码 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
@@ -16,16 +13,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
|
||||
const { userId } = await authUser({ req, authToken: true });
|
||||
|
||||
const id = nanoid();
|
||||
await connectToDatabase();
|
||||
const { code_url, orderId } = await getWxPayQRUrl(amount);
|
||||
|
||||
const code_url = await nativePay(amount * 100, id);
|
||||
|
||||
// 充值记录 + 1
|
||||
// add one pay record
|
||||
const payOrder = await Pay.create({
|
||||
userId,
|
||||
price: amount * PRICE_SCALE,
|
||||
orderId: id
|
||||
orderId
|
||||
});
|
||||
|
||||
jsonRes(res, {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { POST } from './request';
|
||||
import { GET, POST } from './request';
|
||||
import type { SendCodeBody, AuthCodeBody } from './plugins.d';
|
||||
|
||||
export const sendCode = (data: SendCodeBody) => POST(global.systemPlugins.authCode?.sendUrl, data);
|
||||
@@ -8,3 +8,14 @@ export const textCensor = (data: { text: string }) => {
|
||||
if (!global.systemPlugins.censor?.textUrl) return;
|
||||
return POST(global.systemPlugins.censor?.textUrl, data);
|
||||
};
|
||||
|
||||
export const getWxPayQRUrl = (amount: number) =>
|
||||
POST<{
|
||||
code_url: string;
|
||||
orderId: string;
|
||||
}>(global.systemPlugins.pay?.getWxQRUrl, { amount });
|
||||
export const getWxPayQRResult = (orderId: string) =>
|
||||
POST<{
|
||||
trade_state: string;
|
||||
trade_state_desc: string;
|
||||
}>(global.systemPlugins.pay?.getWxQRResult, { orderId });
|
||||
|
@@ -37,7 +37,7 @@ function checkRes(data: ResponseDataType) {
|
||||
if (data === undefined) {
|
||||
console.log('error->', data, 'data is empty');
|
||||
return Promise.reject('服务器异常');
|
||||
} else if (data.code < 200 || data.code >= 400) {
|
||||
} else if (data?.code && (data.code < 200 || data.code >= 400)) {
|
||||
return Promise.reject(data);
|
||||
}
|
||||
return data.data;
|
||||
@@ -90,7 +90,6 @@ function request(url: string, data: any, config: ConfigType, method: Method): an
|
||||
|
||||
return instance
|
||||
.request({
|
||||
baseURL: '/api',
|
||||
url,
|
||||
method,
|
||||
data: ['POST', 'PUT'].includes(method) ? data : null,
|
||||
|
@@ -1,73 +0,0 @@
|
||||
import * as nodemailer from 'nodemailer';
|
||||
import { UserAuthTypeEnum } from '@/constants/common';
|
||||
import Dysmsapi, * as dysmsapi from '@alicloud/dysmsapi20170525';
|
||||
// @ts-ignore
|
||||
import * as OpenApi from '@alicloud/openapi-client';
|
||||
// @ts-ignore
|
||||
import * as Util from '@alicloud/tea-util';
|
||||
|
||||
const myEmail = process.env.MY_MAIL;
|
||||
const mailTransport = nodemailer.createTransport({
|
||||
// host: 'smtp.qq.phone',
|
||||
service: 'qq',
|
||||
secure: true, //安全方式发送,建议都加上
|
||||
auth: {
|
||||
user: myEmail,
|
||||
pass: process.env.MAILE_CODE
|
||||
}
|
||||
});
|
||||
|
||||
const emailMap: { [key: string]: any } = {
|
||||
[UserAuthTypeEnum.register]: {
|
||||
subject: `注册 ${global.feConfigs?.systemTitle} 账号`,
|
||||
html: (code: string) =>
|
||||
`<div>您正在注册 ${global.feConfigs?.systemTitle} 账号,验证码为:${code}</div>`
|
||||
},
|
||||
[UserAuthTypeEnum.findPassword]: {
|
||||
subject: `修改 ${global.feConfigs?.systemTitle} 密码`,
|
||||
html: (code: string) =>
|
||||
`<div>您正在修改 ${global.feConfigs?.systemTitle} 账号密码,验证码为:${code}</div>`
|
||||
}
|
||||
};
|
||||
|
||||
export const sendEmailCode = (email: string, code: string, type: `${UserAuthTypeEnum}`) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = {
|
||||
from: `"${global.feConfigs?.systemTitle}" ${myEmail}`,
|
||||
to: email,
|
||||
subject: emailMap[type]?.subject,
|
||||
html: emailMap[type]?.html(code)
|
||||
};
|
||||
mailTransport.sendMail(options, function (err, msg) {
|
||||
if (err) {
|
||||
console.log('send email error->', err);
|
||||
reject('发生邮件异常');
|
||||
} else {
|
||||
resolve('');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const sendPhoneCode = async (phone: string, code: string) => {
|
||||
const accessKeyId = process.env.aliAccessKeyId;
|
||||
const accessKeySecret = process.env.aliAccessKeySecret;
|
||||
const signName = process.env.aliSignName;
|
||||
const templateCode = process.env.aliTemplateCode;
|
||||
const endpoint = 'dysmsapi.aliyuncs.com';
|
||||
|
||||
const sendSmsRequest = new dysmsapi.SendSmsRequest({
|
||||
phoneNumbers: phone,
|
||||
signName,
|
||||
templateCode,
|
||||
templateParam: `{"code":${code}}`
|
||||
});
|
||||
|
||||
const config = new OpenApi.Config({ accessKeyId, accessKeySecret, endpoint });
|
||||
const client = new Dysmsapi(config);
|
||||
const runtime = new Util.RuntimeOptions({});
|
||||
const res = await client.sendSmsWithOptions(sendSmsRequest, runtime);
|
||||
if (res.body.code !== 'OK') {
|
||||
return Promise.reject(res.body.message || '发送短信失败');
|
||||
}
|
||||
};
|
4
client/src/types/index.d.ts
vendored
4
client/src/types/index.d.ts
vendored
@@ -40,6 +40,10 @@ export type PluginType = {
|
||||
censor?: {
|
||||
textUrl?: string;
|
||||
};
|
||||
pay?: {
|
||||
getWxQRUrl?: string;
|
||||
getWxQRResult?: string;
|
||||
};
|
||||
};
|
||||
|
||||
declare global {
|
||||
|
Reference in New Issue
Block a user