feat: payjs payment channel is ready

This commit is contained in:
RockYang 2024-01-07 14:36:02 +08:00
parent 706aacd8e6
commit 8ec85e2829
11 changed files with 279 additions and 88 deletions

View File

@ -58,6 +58,10 @@ WeChatBot = false
BotToken = "" BotToken = ""
GuildId = "" GuildId = ""
ChanelId = "" ChanelId = ""
UseCDN = false #是否使用反向代理访问设置为true下面的设置才会生效
DiscordAPI = "https://mj.r9it.com:8001" # discord API 反代地址
DiscordCDN = "https://mj.r9it.com:8002" # mj 图片反代地址
DiscordGateway = "wss://mj.r9it.com:8003" # discord 机器人反代地址
[[MjConfigs]] [[MjConfigs]]
Enabled = false Enabled = false
@ -65,6 +69,16 @@ WeChatBot = false
BotToken = "" BotToken = ""
GuildId = "" GuildId = ""
ChanelId = "" ChanelId = ""
UseCDN = false #是否使用反向代理访问设置为true下面的设置才会生效
DiscordAPI = "https://mj.r9it.com:8001" # discord API 反代地址
DiscordCDN = "https://mj.r9it.com:8002" # mj 图片反代地址
DiscordGateway = "wss://mj.r9it.com:8003" # discord 机器人反代地址
[[SdConfigs]]
Enabled = false
ApiURL = ""
ApiKey = ""
Txt2ImgJsonPath = "res/sd/text2img.json"
[[SdConfigs]] [[SdConfigs]]
Enabled = false Enabled = false
@ -95,4 +109,27 @@ WeChatBot = false
PublicKey = "certs/alipay/appPublicCert.crt" # 应用公钥证书 PublicKey = "certs/alipay/appPublicCert.crt" # 应用公钥证书
AlipayPublicKey = "certs/alipay/alipayPublicCert.crt" # 支付宝公钥证书 AlipayPublicKey = "certs/alipay/alipayPublicCert.crt" # 支付宝公钥证书
RootCert = "certs/alipay/alipayRootCert.crt" # 支付宝根证书 RootCert = "certs/alipay/alipayRootCert.crt" # 支付宝根证书
NotifyURL = "http://r9it.com:6004/api/payment/alipay/notify" # 支付异步回调地址 NotifyURL = "https://ai.r9it.com/api/payment/alipay/notify" # 支付异步回调地址
[HuPiPayConfig]
Enabled = false
Name = "wechat"
AppId = "201906161477"
AppSecret = "7f403199d510fb2c6f0b9f2311800e7c"
PayURL = "https://api.xunhupay.com/payment/do.html"
NotifyURL = "https://ai.r9it.com/api/payment/hupipay/notify"
[SmtpConfig] # 注意阿里云服务器禁用了25号端口所以如果需要使用邮件功能请别用阿里云服务器
Host = "smtp.163.com"
Port = 25
AppName = "极客学长"
From = "test@163.com" # 发件邮箱人地址
Password = "" #邮箱 stmp 服务授权码
[JPayConfig] # PayJs 支付配置
Enabled = false
Name = "wechat" # 请不要改动
AppId = "" # 商户 ID
PrivateKey = "" # 秘钥
ApiURL = "https://payjs.cn/api/native"
NotifyURL = "https://ai.r9it.com/api/payment/payjs/notify" # 异步回调地址,域名改成你自己的

View File

@ -39,6 +39,7 @@ type SmtpConfig struct {
// JPayConfig PayJs 支付配置 // JPayConfig PayJs 支付配置
type JPayConfig struct { type JPayConfig struct {
Enabled bool Enabled bool
Name string // 支付名称,默认 wechat
AppId string // 商户 ID AppId string // 商户 ID
PrivateKey string // 私钥 PrivateKey string // 私钥
ApiURL string // API 网关 ApiURL string // API 网关
@ -96,8 +97,8 @@ type HuPiPayConfig struct { //虎皮椒第四方支付配置
Name string // 支付名称wechat/alipay Name string // 支付名称wechat/alipay
AppId string // App ID AppId string // App ID
AppSecret string // app 密钥 AppSecret string // app 密钥
NotifyURL string // 异步通知回调
PayURL string // 支付网关 PayURL string // 支付网关
NotifyURL string // 异步通知回调
} }
type XXLConfig struct { // XXL 任务调度配置 type XXLConfig struct { // XXL 任务调度配置

View File

@ -11,17 +11,20 @@ import (
"embed" "embed"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"github.com/gin-gonic/gin" "math"
"gorm.io/gorm"
"net/http" "net/http"
"net/url" "net/url"
"sync" "sync"
"time" "time"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
) )
const ( const (
PayWayAlipay = "支付宝" PayWayAlipay = "支付宝"
PayWayXunHu = "虎皮椒" PayWayXunHu = "虎皮椒"
PayWayJs = "PayJS"
) )
// PaymentHandler 支付服务回调 handler // PaymentHandler 支付服务回调 handler
@ -29,16 +32,25 @@ type PaymentHandler struct {
BaseHandler BaseHandler
alipayService *payment.AlipayService alipayService *payment.AlipayService
huPiPayService *payment.HuPiPayService huPiPayService *payment.HuPiPayService
js *payment.PayJS
snowflake *service.Snowflake snowflake *service.Snowflake
db *gorm.DB db *gorm.DB
fs embed.FS fs embed.FS
lock sync.Mutex lock sync.Mutex
} }
func NewPaymentHandler(server *core.AppServer, alipayService *payment.AlipayService, huPiPayService *payment.HuPiPayService, snowflake *service.Snowflake, db *gorm.DB, fs embed.FS) *PaymentHandler { func NewPaymentHandler(
server *core.AppServer,
alipayService *payment.AlipayService,
huPiPayService *payment.HuPiPayService,
js *payment.PayJS,
snowflake *service.Snowflake,
db *gorm.DB,
fs embed.FS) *PaymentHandler {
h := PaymentHandler{ h := PaymentHandler{
alipayService: alipayService, alipayService: alipayService,
huPiPayService: huPiPayService, huPiPayService: huPiPayService,
js: js,
snowflake: snowflake, snowflake: snowflake,
fs: fs, fs: fs,
db: db, db: db,
@ -81,17 +93,14 @@ func (h *PaymentHandler) DoPay(c *gin.Context) {
c.Redirect(302, uri) c.Redirect(302, uri)
return return
} else if payWay == "hupi" { // 虎皮椒支付 } else if payWay == "hupi" { // 虎皮椒支付
params := map[string]string{ params := payment.HuPiPayReq{
"version": "1.1", Version: "1.1",
"trade_order_id": orderNo, TradeOrderId: orderNo,
"total_fee": fmt.Sprintf("%f", order.Amount), TotalFee: fmt.Sprintf("%f", order.Amount),
"title": order.Subject, Title: order.Subject,
"notify_url": h.App.Config.HuPiPayConfig.NotifyURL, NotifyURL: h.App.Config.HuPiPayConfig.NotifyURL,
"return_url": "", WapName: "极客学长",
"wap_name": "极客学长",
"callback_url": "",
} }
res, err := h.huPiPayService.Pay(params) res, err := h.huPiPayService.Pay(params)
if err != nil { if err != nil {
resp.ERROR(c, "error with generate pay url: "+err.Error()) resp.ERROR(c, "error with generate pay url: "+err.Error())
@ -189,9 +198,14 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
return return
} }
payWay := PayWayAlipay var payWay string
if data.PayWay == "hupi" { switch data.PayWay {
case "hupi":
payWay = PayWayXunHu payWay = PayWayXunHu
case "payjs":
payWay = PayWayJs
default:
payWay = PayWayAlipay
} }
// 创建订单 // 创建订单
remark := types.OrderRemark{ remark := types.OrderRemark{
@ -219,6 +233,23 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
return return
} }
// PayJs 单独处理,只能用官方生成的二维码
if data.PayWay == "payjs" {
params := payment.JPayReq{
TotalFee: int(math.Ceil(order.Amount * 100)),
OutTradeNo: order.OrderNo,
Subject: product.Name,
}
r := h.js.Pay(params)
if r.IsOK() {
resp.SUCCESS(c, gin.H{"order_no": order.OrderNo, "image": r.Qrcode})
return
} else {
resp.ERROR(c, "error with generating payment qrcode: "+r.ReturnMsg)
return
}
}
var logo string var logo string
if data.PayWay == "alipay" { if data.PayWay == "alipay" {
logo = "res/img/alipay.jpg" logo = "res/img/alipay.jpg"
@ -252,35 +283,6 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
resp.SUCCESS(c, gin.H{"order_no": orderNo, "image": fmt.Sprintf("data:image/jpg;base64, %s", imgDataBase64), "url": imageURL}) resp.SUCCESS(c, gin.H{"order_no": orderNo, "image": fmt.Sprintf("data:image/jpg;base64, %s", imgDataBase64), "url": imageURL})
} }
// AlipayNotify 支付宝支付回调
func (h *PaymentHandler) AlipayNotify(c *gin.Context) {
err := c.Request.ParseForm()
if err != nil {
c.String(http.StatusOK, "fail")
return
}
// TODO这里最好用支付宝的公钥签名签证一下交易真假
//res := h.alipayService.TradeVerify(c.Request.Form)
r := h.alipayService.TradeQuery(c.Request.Form.Get("out_trade_no"))
logger.Infof("验证支付结果:%+v", r)
if !r.Success() {
c.String(http.StatusOK, "fail")
return
}
h.lock.Lock()
defer h.lock.Unlock()
err = h.notify(r.OutTradeNo)
if err != nil {
c.String(http.StatusOK, "fail")
return
}
c.String(http.StatusOK, "success")
}
// 异步通知回调公共逻辑 // 异步通知回调公共逻辑
func (h *PaymentHandler) notify(orderNo string) error { func (h *PaymentHandler) notify(orderNo string) error {
var order model.Order var order model.Order
@ -370,6 +372,9 @@ func (h *PaymentHandler) GetPayWays(c *gin.Context) {
if h.App.Config.HuPiPayConfig.Enabled { if h.App.Config.HuPiPayConfig.Enabled {
data["hupi"] = gin.H{"name": h.App.Config.HuPiPayConfig.Name} data["hupi"] = gin.H{"name": h.App.Config.HuPiPayConfig.Name}
} }
if h.App.Config.JPayConfig.Enabled {
data["payjs"] = gin.H{"name": h.App.Config.JPayConfig.Name}
}
resp.SUCCESS(c, data) resp.SUCCESS(c, data)
} }
@ -395,3 +400,60 @@ func (h *PaymentHandler) HuPiPayNotify(c *gin.Context) {
c.String(http.StatusOK, "success") c.String(http.StatusOK, "success")
} }
// AlipayNotify 支付宝支付回调
func (h *PaymentHandler) AlipayNotify(c *gin.Context) {
err := c.Request.ParseForm()
if err != nil {
c.String(http.StatusOK, "fail")
return
}
// TODO这里最好用支付宝的公钥签名签证一下交易真假
//res := h.alipayService.TradeVerify(c.Request.Form)
r := h.alipayService.TradeQuery(c.Request.Form.Get("out_trade_no"))
logger.Infof("验证支付结果:%+v", r)
if !r.Success() {
c.String(http.StatusOK, "fail")
return
}
h.lock.Lock()
defer h.lock.Unlock()
err = h.notify(r.OutTradeNo)
if err != nil {
c.String(http.StatusOK, "fail")
return
}
c.String(http.StatusOK, "success")
}
// PayJsNotify PayJs 支付异步回调
func (h *PaymentHandler) PayJsNotify(c *gin.Context) {
err := c.Request.ParseForm()
if err != nil {
c.String(http.StatusOK, "fail")
return
}
orderNo := c.Request.Form.Get("out_trade_no")
returnCode := c.Request.Form.Get("return_code")
logger.Infof("收到订单支付回调,订单 NO%s支付结果代码%v", orderNo, returnCode)
// 支付失败
if returnCode != "1" {
return
}
h.lock.Lock()
defer h.lock.Unlock()
err = h.notify(orderNo)
if err != nil {
c.String(http.StatusOK, "fail")
return
}
c.String(http.StatusOK, "success")
}

View File

@ -6,9 +6,10 @@ import (
"chatplus/service" "chatplus/service"
"chatplus/utils" "chatplus/utils"
"chatplus/utils/resp" "chatplus/utils/resp"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
"strings"
) )
const CodeStorePrefix = "/verify/codes/" const CodeStorePrefix = "/verify/codes/"
@ -52,8 +53,16 @@ func (h *SmsHandler) SendCode(c *gin.Context) {
code := utils.RandomNumber(6) code := utils.RandomNumber(6)
var err error var err error
if strings.Contains(data.Receiver, "@") { // email if strings.Contains(data.Receiver, "@") { // email
if !utils.ContainsStr(h.App.SysConfig.RegisterWays, "email") {
resp.ERROR(c, "系统已禁用邮箱注册!")
return
}
err = h.smtp.SendVerifyCode(data.Receiver, code) err = h.smtp.SendVerifyCode(data.Receiver, code)
} else { } else {
if !utils.ContainsStr(h.App.SysConfig.RegisterWays, "mobile") {
resp.ERROR(c, "系统已禁用手机号注册!")
return
}
err = h.sms.SendVerifyCode(data.Receiver, code) err = h.sms.SendVerifyCode(data.Receiver, code)
} }
if err != nil { if err != nil {

View File

@ -2,6 +2,7 @@ package handler
import ( import (
"chatplus/service" "chatplus/service"
"chatplus/service/payment"
"chatplus/store/model" "chatplus/store/model"
"chatplus/utils" "chatplus/utils"
"chatplus/utils/resp" "chatplus/utils/resp"
@ -14,15 +15,30 @@ import (
type TestHandler struct { type TestHandler struct {
db *gorm.DB db *gorm.DB
snowflake *service.Snowflake snowflake *service.Snowflake
js *payment.PayJS
} }
func NewTestHandler(db *gorm.DB, snowflake *service.Snowflake) *TestHandler { func NewTestHandler(db *gorm.DB, snowflake *service.Snowflake, js *payment.PayJS) *TestHandler {
return &TestHandler{db: db, snowflake: snowflake} return &TestHandler{db: db, snowflake: snowflake, js: js}
} }
func (h *TestHandler) Test(c *gin.Context) { func (h *TestHandler) Test(c *gin.Context) {
h.initUserNickname(c) //h.initUserNickname(c)
h.initMjTaskId(c) //h.initMjTaskId(c)
orderId, _ := h.snowflake.Next(false)
params := payment.JPayReq{
TotalFee: 12345,
OutTradeNo: orderId,
Subject: "支付测试",
}
r := h.js.Pay(params)
if !r.IsOK() {
resp.ERROR(c, r.ReturnMsg)
return
}
resp.SUCCESS(c, r)
} }
func (h *TestHandler) initUserNickname(c *gin.Context) { func (h *TestHandler) initUserNickname(c *gin.Context) {

View File

@ -170,6 +170,7 @@ func main() {
fx.Provide(payment.NewAlipayService), fx.Provide(payment.NewAlipayService),
fx.Provide(payment.NewHuPiPay), fx.Provide(payment.NewHuPiPay),
fx.Provide(payment.NewPayJS),
fx.Provide(service.NewSnowflake), fx.Provide(service.NewSnowflake),
fx.Provide(service.NewXXLJobExecutor), fx.Provide(service.NewXXLJobExecutor),
fx.Invoke(func(exec *service.XXLJobExecutor, config *types.AppConfig) { fx.Invoke(func(exec *service.XXLJobExecutor, config *types.AppConfig) {
@ -306,6 +307,7 @@ func main() {
group.POST("qrcode", h.PayQrcode) group.POST("qrcode", h.PayQrcode)
group.POST("alipay/notify", h.AlipayNotify) group.POST("alipay/notify", h.AlipayNotify)
group.POST("hupipay/notify", h.HuPiPayNotify) group.POST("hupipay/notify", h.HuPiPayNotify)
group.POST("payjs/notify", h.PayJsNotify)
}), }),
fx.Invoke(func(s *core.AppServer, h *admin.ProductHandler) { fx.Invoke(func(s *core.AppServer, h *admin.ProductHandler) {
group := s.Engine.Group("/api/admin/product/") group := s.Engine.Group("/api/admin/product/")

View File

@ -4,10 +4,11 @@ import (
"chatplus/core/types" "chatplus/core/types"
"chatplus/store" "chatplus/store"
"chatplus/store/model" "chatplus/store/model"
"gorm.io/gorm"
"strings" "strings"
"sync/atomic" "sync/atomic"
"time" "time"
"gorm.io/gorm"
) )
// Service MJ 绘画服务 // Service MJ 绘画服务
@ -121,7 +122,7 @@ func (s *Service) Notify(data CBReq) {
return return
} }
tx := s.db.Session(&gorm.Session{}).Order("id ASC") tx := s.db.Session(&gorm.Session{}).Where("progress < ?", 100).Order("id ASC")
if data.ReferenceId != "" { if data.ReferenceId != "" {
tx = tx.Where("reference_id = ?", data.ReferenceId) tx = tx.Where("reference_id = ?", data.ReferenceId)
} else { } else {

View File

@ -2,6 +2,7 @@ package payment
import ( import (
"chatplus/core/types" "chatplus/core/types"
"chatplus/utils"
"crypto/md5" "crypto/md5"
"fmt" "fmt"
"io" "io"
@ -27,17 +28,37 @@ func NewHuPiPay(config *types.AppConfig) *HuPiPayService {
} }
} }
type HuPiPayReq struct {
AppId string `json:"appid"`
Version string `json:"version"`
TradeOrderId string `json:"trade_order_id"`
TotalFee string `json:"total_fee"`
Title string `json:"title"`
NotifyURL string `json:"notify_url"`
ReturnURL string `json:"return_url"`
WapName string `json:"wap_name"`
CallbackURL string `json:"callback_url"`
Time string `json:"time"`
NonceStr string `json:"nonce_str"`
}
// Pay 执行支付请求操作 // Pay 执行支付请求操作
func (s *HuPiPayService) Pay(params map[string]string) (string, error) { func (s *HuPiPayService) Pay(params HuPiPayReq) (string, error) {
data := url.Values{} data := url.Values{}
simple := strconv.FormatInt(time.Now().Unix(), 10) simple := strconv.FormatInt(time.Now().Unix(), 10)
params["appid"] = s.appId params.AppId = s.appId
params["time"] = simple params.Time = simple
params["nonce_str"] = simple params.NonceStr = simple
for k, v := range params { encode := utils.JsonEncode(params)
data.Add(k, v) m := make(map[string]string)
_ = utils.JsonDecode(encode, &m)
for k, v := range m {
data.Add(k, fmt.Sprintf("%v", v))
} }
data.Add("hash", s.Sign(params)) encode = utils.JsonEncode(params)
m = make(map[string]string)
_ = utils.JsonDecode(encode, &m)
data.Add("hash", s.Sign(m))
resp, err := http.PostForm(s.host, data) resp, err := http.PostForm(s.host, data)
if err != nil { if err != nil {
return "error", err return "error", err
@ -54,7 +75,6 @@ func (s *HuPiPayService) Pay(params map[string]string) (string, error) {
func (s *HuPiPayService) Sign(params map[string]string) string { func (s *HuPiPayService) Sign(params map[string]string) string {
var data string var data string
keys := make([]string, 0, 0) keys := make([]string, 0, 0)
params["appid"] = s.appId
for key := range params { for key := range params {
keys = append(keys, key) keys = append(keys, key)
} }

View File

@ -26,9 +26,55 @@ func NewPayJS(appConfig *types.AppConfig) *PayJS {
type JPayReq struct { type JPayReq struct {
TotalFee int `json:"total_fee"` TotalFee int `json:"total_fee"`
OutTradeNo string `json:"out_trade_no"` OutTradeNo string `json:"out_trade_no"`
Body string `json:"body"` Subject string `json:"body"`
NotifyURL string `json:"notify_url"` NotifyURL string `json:"notify_url"`
} }
type JPayReps struct {
CodeUrl string `json:"code_url"`
OutTradeNo string `json:"out_trade_no"`
OrderId string `json:"payjs_order_id"`
Qrcode string `json:"qrcode"`
ReturnCode int `json:"return_code"`
ReturnMsg string `json:"return_msg"`
Sign string `json:"sign"`
TotalFee string `json:"total_fee"`
}
func (r JPayReps) IsOK() bool {
return r.ReturnMsg == "SUCCESS"
}
func (js *PayJS) Pay(param JPayReq) JPayReps {
param.NotifyURL = js.config.NotifyURL
var p = url.Values{}
encode := utils.JsonEncode(param)
m := make(map[string]interface{})
_ = utils.JsonDecode(encode, &m)
for k, v := range m {
p.Add(k, fmt.Sprintf("%v", v))
}
p.Add("mchid", js.config.AppId)
p.Add("sign", sign(p, js.config.PrivateKey))
cli := http.Client{}
r, err := cli.PostForm(js.config.ApiURL, p)
if err != nil {
return JPayReps{ReturnMsg: err.Error()}
}
defer r.Body.Close()
bs, err := io.ReadAll(r.Body)
if err != nil {
return JPayReps{ReturnMsg: err.Error()}
}
var data JPayReps
err = utils.JsonDecode(string(bs), &data)
if err != nil {
return JPayReps{ReturnMsg: err.Error()}
}
return data
}
func sign(params url.Values, priKey string) string { func sign(params url.Values, priKey string) string {
params.Del(`sign`) params.Del(`sign`)
@ -54,28 +100,3 @@ func sign(params url.Values, priKey string) string {
md5res := hex.EncodeToString(md5bs[:]) md5res := hex.EncodeToString(md5bs[:])
return strings.ToUpper(md5res) return strings.ToUpper(md5res)
} }
func (pj *PayJS) Pay(param JPayReq) (string, error) {
var p = url.Values{}
encode := utils.JsonEncode(param)
m := make(map[string]interface{})
_ = utils.JsonDecode(encode, &m)
for k, v := range m {
p.Add(k, fmt.Sprintf("%v", v))
}
p.Add("mchid", pj.config.AppId)
p.Add("sign", sign(p, pj.config.PrivateKey))
cli := http.Client{}
r, err := cli.PostForm(pj.config.ApiURL, p)
if err != nil {
return "", err
}
defer r.Body.Close()
bs, err := io.ReadAll(r.Body)
if err != nil {
return "", err
}
return string(bs), nil
}

View File

@ -71,6 +71,10 @@
<span v-if="payWays['hupi']['name'] === 'wechat'"><i class="iconfont icon-wechat-pay"></i> 微信</span> <span v-if="payWays['hupi']['name'] === 'wechat'"><i class="iconfont icon-wechat-pay"></i> 微信</span>
<span v-else><i class="iconfont icon-alipay"></i> 支付宝</span> <span v-else><i class="iconfont icon-alipay"></i> 支付宝</span>
</el-button> </el-button>
<el-button type="success" @click="PayJs(scope.item)" size="small" v-if="payWays['payjs']">
<span><i class="iconfont icon-wechat-pay"></i> 微信</span>
</el-button>
</div> </div>
</div> </div>
</div> </div>
@ -280,7 +284,20 @@ const huPiPay = (row) => {
curPayProduct.value = row curPayProduct.value = row
} }
genPayQrcode() genPayQrcode()
}
// PayJS
const PayJs = (row) => {
payName.value = '微信'
curPay.value = "payjs"
if (!user.value.id) {
showLoginDialog.value = true
return
}
if (row) {
curPayProduct.value = row
}
genPayQrcode()
} }
const queryOrder = (orderNo) => { const queryOrder = (orderNo) => {
@ -290,7 +307,11 @@ const queryOrder = (orderNo) => {
queryOrder(orderNo) queryOrder(orderNo)
} else if (res.data.status === 2) { } else if (res.data.status === 2) {
text.value = "支付成功,正在刷新页面" text.value = "支付成功,正在刷新页面"
setTimeout(() => location.reload(), 500) if (curPay.value === "payjs") {
setTimeout(() => location.reload(), 3000)
} else {
setTimeout(() => location.reload(), 500)
}
} else { } else {
// //
if (activeOrderNo.value === orderNo) { if (activeOrderNo.value === orderNo) {

View File

@ -284,6 +284,7 @@ const functionSet = (filed, row) => {
const generateToken = () => { const generateToken = () => {
httpGet('/api/admin/function/token').then(res => { httpGet('/api/admin/function/token').then(res => {
ElMessage.success("生成 Token 成功")
item.value.token = res.data item.value.token = res.data
}).catch(() => { }).catch(() => {
ElMessage.error("生成 Token 失败") ElMessage.error("生成 Token 失败")