mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	wechat payment is ready for PC
This commit is contained in:
		@@ -1,6 +1,7 @@
 | 
			
		||||
# 更新日志
 | 
			
		||||
## v4.0.9
 | 
			
		||||
* 环境升级:升级 Golang 到 go1.22.4
 | 
			
		||||
* 功能增加:接入微信商户号支付渠道
 | 
			
		||||
* Bug修复:修复前端页面菜单把页面撑开,底部留白问题
 | 
			
		||||
* 功能优化:聊天页面自动根据内容调整输入框的高度
 | 
			
		||||
* Bug修复:修复Dalle绘图失败退回算力的问题
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								api/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								api/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -17,4 +17,5 @@ bin
 | 
			
		||||
data
 | 
			
		||||
config.toml
 | 
			
		||||
static/upload 
 | 
			
		||||
storage.json
 | 
			
		||||
storage.json 
 | 
			
		||||
res/certs/wechat/apiclient_key.pem
 | 
			
		||||
 
 | 
			
		||||
@@ -233,6 +233,7 @@ func needLogin(c *gin.Context) bool {
 | 
			
		||||
		c.Request.URL.Path == "/api/payment/alipay/notify" ||
 | 
			
		||||
		c.Request.URL.Path == "/api/payment/hupipay/notify" ||
 | 
			
		||||
		c.Request.URL.Path == "/api/payment/payjs/notify" ||
 | 
			
		||||
		c.Request.URL.Path == "/api/payment/wechat/notify" ||
 | 
			
		||||
		c.Request.URL.Path == "/api/payment/doPay" ||
 | 
			
		||||
		c.Request.URL.Path == "/api/payment/payWays" ||
 | 
			
		||||
		strings.HasPrefix(c.Request.URL.Path, "/api/test") ||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,11 +29,12 @@ type AppConfig struct {
 | 
			
		||||
	WeChatBot      bool                    // 是否启用微信机器人
 | 
			
		||||
	SdConfigs      []StableDiffusionConfig // sd AI draw service pool
 | 
			
		||||
 | 
			
		||||
	XXLConfig     XXLConfig
 | 
			
		||||
	AlipayConfig  AlipayConfig
 | 
			
		||||
	HuPiPayConfig HuPiPayConfig
 | 
			
		||||
	SmtpConfig    SmtpConfig // 邮件发送配置
 | 
			
		||||
	JPayConfig    JPayConfig // payjs 支付配置
 | 
			
		||||
	XXLConfig       XXLConfig
 | 
			
		||||
	AlipayConfig    AlipayConfig    // 支付宝支付渠道配置
 | 
			
		||||
	HuPiPayConfig   HuPiPayConfig   // 虎皮椒支付配置
 | 
			
		||||
	SmtpConfig      SmtpConfig      // 邮件发送配置
 | 
			
		||||
	JPayConfig      JPayConfig      // payjs 支付配置
 | 
			
		||||
	WechatPayConfig WechatPayConfig // 微信支付渠道配置
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SmtpConfig struct {
 | 
			
		||||
@@ -85,6 +86,17 @@ type AlipayConfig struct {
 | 
			
		||||
	ReturnURL       string // 支付成功返回地址
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type WechatPayConfig struct {
 | 
			
		||||
	Enabled    bool   // 是否启用该支付通道
 | 
			
		||||
	AppId      string // 公众号的APPID,如:wxd678efh567hg6787
 | 
			
		||||
	MchId      string // 直连商户的商户号,由微信支付生成并下发
 | 
			
		||||
	SerialNo   string // 商户证书的证书序列号
 | 
			
		||||
	PrivateKey string // 用户私钥文件路径
 | 
			
		||||
	ApiV3Key   string // API V3 秘钥
 | 
			
		||||
	NotifyURL  string // 异步通知回调
 | 
			
		||||
	ReturnURL  string // 支付成功返回地址
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type HuPiPayConfig struct { //虎皮椒第四方支付配置
 | 
			
		||||
	Enabled   bool   // 是否启用该支付通道
 | 
			
		||||
	Name      string // 支付名称,如:wechat/alipay
 | 
			
		||||
@@ -182,8 +194,9 @@ var QWen = Platform{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SystemConfig struct {
 | 
			
		||||
	Title         string `json:"title,omitempty"`
 | 
			
		||||
	AdminTitle    string `json:"admin_title,omitempty"`
 | 
			
		||||
	Title         string `json:"title,omitempty"`       // 网站标题
 | 
			
		||||
	Slogan        string `json:"slogan,omitempty"`      // 网站 slogan
 | 
			
		||||
	AdminTitle    string `json:"admin_title,omitempty"` // 管理后台标题
 | 
			
		||||
	Logo          string `json:"logo,omitempty"`
 | 
			
		||||
	InitPower     int    `json:"init_power,omitempty"`      // 新用户注册赠送算力值
 | 
			
		||||
	DailyPower    int    `json:"daily_power,omitempty"`     // 每日赠送算力
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,8 @@ require (
 | 
			
		||||
require (
 | 
			
		||||
	github.com/go-ole/go-ole v1.2.6 // indirect
 | 
			
		||||
	github.com/go-pay/crypto v0.0.1 // indirect
 | 
			
		||||
	github.com/go-pay/errgroup v0.0.2 // indirect
 | 
			
		||||
	github.com/go-pay/util v0.0.2 // indirect
 | 
			
		||||
	github.com/go-pay/xlog v0.0.2 // indirect
 | 
			
		||||
	github.com/go-pay/xtime v0.0.2 // indirect
 | 
			
		||||
	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
 | 
			
		||||
 
 | 
			
		||||
@@ -47,6 +47,8 @@ github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
 | 
			
		||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
 | 
			
		||||
github.com/go-pay/crypto v0.0.1 h1:B6InT8CLfSLc6nGRVx9VMJRBBazFMjr293+jl0lLXUY=
 | 
			
		||||
github.com/go-pay/crypto v0.0.1/go.mod h1:41oEIvHMKbNcYlWUlRWtsnC6+ASgh7u29z0gJXe5bes=
 | 
			
		||||
github.com/go-pay/errgroup v0.0.2 h1:5mZMdm0TDClDm2S3G0/sm0f8AuQRtz0dOrTHDR9R8Cc=
 | 
			
		||||
github.com/go-pay/errgroup v0.0.2/go.mod h1:0+4b8mvFMS71MIzsaC+gVvB4x37I93lRb2dqrwuU8x8=
 | 
			
		||||
github.com/go-pay/gopay v1.5.101 h1:rVb+sfv6hiQtknAlZnTTLvU27NvFJ4p0yglN/vPpGXI=
 | 
			
		||||
github.com/go-pay/gopay v1.5.101/go.mod h1:AW4Yj8jDZX9BM1/GTLTY1Gy5SHjiq8kQvG5sBTN2sxI=
 | 
			
		||||
github.com/go-pay/util v0.0.2 h1:goJ4f6kNY5zzdtg1Cj8oWC+Cw7bfg/qq2rJangMAb9U=
 | 
			
		||||
 
 | 
			
		||||
@@ -29,39 +29,48 @@ import (
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	PayWayAlipay = "支付宝"
 | 
			
		||||
	PayWayXunHu  = "虎皮椒"
 | 
			
		||||
	PayWayJs     = "PayJS"
 | 
			
		||||
type PayWay struct {
 | 
			
		||||
	Name  string `json:"name"`
 | 
			
		||||
	Value string `json:"value"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	PayWayAlipay = PayWay{Name: "支付宝", Value: "alipay"}
 | 
			
		||||
	PayWayXunHu  = PayWay{Name: "虎皮椒", Value: "hupi"}
 | 
			
		||||
	PayWayJs     = PayWay{Name: "PayJS", Value: "payjs"}
 | 
			
		||||
	PayWayWechat = PayWay{Name: "微信支付", Value: "wechat"}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PaymentHandler 支付服务回调 handler
 | 
			
		||||
type PaymentHandler struct {
 | 
			
		||||
	BaseHandler
 | 
			
		||||
	alipayService  *payment.AlipayService
 | 
			
		||||
	huPiPayService *payment.HuPiPayService
 | 
			
		||||
	js             *payment.PayJS
 | 
			
		||||
	snowflake      *service.Snowflake
 | 
			
		||||
	fs             embed.FS
 | 
			
		||||
	lock           sync.Mutex
 | 
			
		||||
	signKey        string // 用来签名的随机秘钥
 | 
			
		||||
	alipayService    *payment.AlipayService
 | 
			
		||||
	huPiPayService   *payment.HuPiPayService
 | 
			
		||||
	jsPayService     *payment.JPayService
 | 
			
		||||
	wechatPayService *payment.WechatPayService
 | 
			
		||||
	snowflake        *service.Snowflake
 | 
			
		||||
	fs               embed.FS
 | 
			
		||||
	lock             sync.Mutex
 | 
			
		||||
	signKey          string // 用来签名的随机秘钥
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewPaymentHandler(
 | 
			
		||||
	server *core.AppServer,
 | 
			
		||||
	alipayService *payment.AlipayService,
 | 
			
		||||
	huPiPayService *payment.HuPiPayService,
 | 
			
		||||
	js *payment.PayJS,
 | 
			
		||||
	jsPayService *payment.JPayService,
 | 
			
		||||
	wechatPayService *payment.WechatPayService,
 | 
			
		||||
	db *gorm.DB,
 | 
			
		||||
	snowflake *service.Snowflake,
 | 
			
		||||
	fs embed.FS) *PaymentHandler {
 | 
			
		||||
	return &PaymentHandler{
 | 
			
		||||
		alipayService:  alipayService,
 | 
			
		||||
		huPiPayService: huPiPayService,
 | 
			
		||||
		js:             js,
 | 
			
		||||
		snowflake:      snowflake,
 | 
			
		||||
		fs:             fs,
 | 
			
		||||
		lock:           sync.Mutex{},
 | 
			
		||||
		alipayService:    alipayService,
 | 
			
		||||
		huPiPayService:   huPiPayService,
 | 
			
		||||
		jsPayService:     jsPayService,
 | 
			
		||||
		wechatPayService: wechatPayService,
 | 
			
		||||
		snowflake:        snowflake,
 | 
			
		||||
		fs:               fs,
 | 
			
		||||
		lock:             sync.Mutex{},
 | 
			
		||||
		BaseHandler: BaseHandler{
 | 
			
		||||
			App: server,
 | 
			
		||||
			DB:  db,
 | 
			
		||||
@@ -108,10 +117,9 @@ func (h *PaymentHandler) DoPay(c *gin.Context) {
 | 
			
		||||
 | 
			
		||||
	// 更新扫码状态
 | 
			
		||||
	h.DB.Model(&order).UpdateColumn("status", types.OrderScanned)
 | 
			
		||||
	if payWay == "alipay" { // 支付宝
 | 
			
		||||
		// 生成支付链接
 | 
			
		||||
		amount := fmt.Sprintf("%.2f", order.Amount)
 | 
			
		||||
 | 
			
		||||
	if payWay == "alipay" { // 支付宝
 | 
			
		||||
		amount := fmt.Sprintf("%.2f", order.Amount)
 | 
			
		||||
		uri, err := h.alipayService.PayUrlMobile(order.OrderNo, amount, order.Subject)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			resp.ERROR(c, "error with generate pay url: "+err.Error())
 | 
			
		||||
@@ -212,14 +220,21 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
 | 
			
		||||
	var notifyURL string
 | 
			
		||||
	switch data.PayWay {
 | 
			
		||||
	case "hupi":
 | 
			
		||||
		payWay = PayWayXunHu
 | 
			
		||||
		payWay = PayWayXunHu.Value
 | 
			
		||||
		notifyURL = h.App.Config.HuPiPayConfig.NotifyURL
 | 
			
		||||
		break
 | 
			
		||||
	case "payjs":
 | 
			
		||||
		payWay = PayWayJs
 | 
			
		||||
		payWay = PayWayJs.Value
 | 
			
		||||
		notifyURL = h.App.Config.JPayConfig.NotifyURL
 | 
			
		||||
	default:
 | 
			
		||||
		payWay = PayWayAlipay
 | 
			
		||||
		break
 | 
			
		||||
	case "alipay":
 | 
			
		||||
		payWay = PayWayAlipay.Value
 | 
			
		||||
		notifyURL = h.App.Config.AlipayConfig.NotifyURL
 | 
			
		||||
		break
 | 
			
		||||
	default:
 | 
			
		||||
		payWay = PayWayWechat.Value
 | 
			
		||||
		notifyURL = h.App.Config.WechatPayConfig.NotifyURL
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	// 创建订单
 | 
			
		||||
	remark := types.OrderRemark{
 | 
			
		||||
@@ -255,7 +270,7 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
 | 
			
		||||
			OutTradeNo: order.OrderNo,
 | 
			
		||||
			Subject:    product.Name,
 | 
			
		||||
		}
 | 
			
		||||
		r := h.js.Pay(params)
 | 
			
		||||
		r := h.jsPayService.Pay(params)
 | 
			
		||||
		if r.IsOK() {
 | 
			
		||||
			resp.SUCCESS(c, gin.H{"order_no": order.OrderNo, "image": r.Qrcode})
 | 
			
		||||
			return
 | 
			
		||||
@@ -274,6 +289,8 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
 | 
			
		||||
		} else {
 | 
			
		||||
			logo = "res/img/alipay.jpg"
 | 
			
		||||
		}
 | 
			
		||||
	} else if data.PayWay == "wechat" {
 | 
			
		||||
		logo = "res/img/wechat-pay.jpg"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	file, err := h.fs.Open(logo)
 | 
			
		||||
@@ -290,7 +307,18 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
 | 
			
		||||
	timestamp := time.Now().Unix()
 | 
			
		||||
	signStr := fmt.Sprintf("%s-%s-%d-%s", orderNo, data.PayWay, timestamp, h.signKey)
 | 
			
		||||
	sign := utils.Sha256(signStr)
 | 
			
		||||
	imageURL := fmt.Sprintf("%s://%s/api/payment/doPay?order_no=%s&pay_way=%s&t=%d&sign=%s", parse.Scheme, parse.Host, orderNo, data.PayWay, timestamp, sign)
 | 
			
		||||
	var imageURL string
 | 
			
		||||
	if data.PayWay == "wechat" {
 | 
			
		||||
		payUrl, err := h.wechatPayService.PayUrlNative(order.OrderNo, int(math.Floor(order.Amount*100)), product.Name)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			resp.ERROR(c, "error with generating wechat payment qrcode: "+err.Error())
 | 
			
		||||
			return
 | 
			
		||||
		} else {
 | 
			
		||||
			imageURL = payUrl
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		imageURL = fmt.Sprintf("%s://%s/api/payment/doPay?order_no=%s&pay_way=%s&t=%d&sign=%s", parse.Scheme, parse.Host, orderNo, data.PayWay, timestamp, sign)
 | 
			
		||||
	}
 | 
			
		||||
	imgData, err := utils.GenQrcode(imageURL, 400, file)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		resp.ERROR(c, err.Error())
 | 
			
		||||
@@ -337,7 +365,7 @@ func (h *PaymentHandler) Mobile(c *gin.Context) {
 | 
			
		||||
	var payURL string
 | 
			
		||||
	switch data.PayWay {
 | 
			
		||||
	case "hupi":
 | 
			
		||||
		payWay = PayWayXunHu
 | 
			
		||||
		payWay = PayWayXunHu.Name
 | 
			
		||||
		notifyURL = h.App.Config.HuPiPayConfig.NotifyURL
 | 
			
		||||
		returnURL = h.App.Config.HuPiPayConfig.ReturnURL
 | 
			
		||||
		parse, _ := url.Parse(h.App.Config.HuPiPayConfig.ReturnURL)
 | 
			
		||||
@@ -356,13 +384,14 @@ func (h *PaymentHandler) Mobile(c *gin.Context) {
 | 
			
		||||
		}
 | 
			
		||||
		r, err := h.huPiPayService.Pay(params)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logger.Error("error with generating Pay URL: ", err.Error())
 | 
			
		||||
			resp.ERROR(c, "error with generating Pay URL: "+err.Error())
 | 
			
		||||
			errMsg := "error with generating Pay Hupi URL: " + err.Error()
 | 
			
		||||
			logger.Error(errMsg)
 | 
			
		||||
			resp.ERROR(c, errMsg)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		payURL = r.URL
 | 
			
		||||
	case "payjs":
 | 
			
		||||
		payWay = PayWayJs
 | 
			
		||||
		payWay = PayWayJs.Name
 | 
			
		||||
		notifyURL = h.App.Config.JPayConfig.NotifyURL
 | 
			
		||||
		returnURL = h.App.Config.JPayConfig.ReturnURL
 | 
			
		||||
		totalFee := decimal.NewFromFloat(product.Price).Sub(decimal.NewFromFloat(product.Discount)).Mul(decimal.NewFromInt(100)).IntPart()
 | 
			
		||||
@@ -372,12 +401,22 @@ func (h *PaymentHandler) Mobile(c *gin.Context) {
 | 
			
		||||
		params.Add("body", product.Name)
 | 
			
		||||
		params.Add("notify_url", notifyURL)
 | 
			
		||||
		params.Add("auto", "0")
 | 
			
		||||
		payURL = h.js.PayH5(params)
 | 
			
		||||
		payURL = h.jsPayService.PayH5(params)
 | 
			
		||||
	case "alipay":
 | 
			
		||||
		payWay = PayWayAlipay
 | 
			
		||||
		payWay = PayWayAlipay.Name
 | 
			
		||||
		payURL, err = h.alipayService.PayUrlMobile(orderNo, fmt.Sprintf("%.2f", amount), product.Name)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			resp.ERROR(c, "error with generating Pay URL: "+err.Error())
 | 
			
		||||
			errMsg := "error with generating Alipay URL: " + err.Error()
 | 
			
		||||
			resp.ERROR(c, errMsg)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	case "wechat":
 | 
			
		||||
		payWay = PayWayWechat.Name
 | 
			
		||||
		payURL, err = h.wechatPayService.PayUrlH5(orderNo, int(amount*100), product.Name, c.ClientIP())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			errMsg := "error with generating Wechat URL: " + err.Error()
 | 
			
		||||
			logger.Error(errMsg)
 | 
			
		||||
			resp.ERROR(c, errMsg)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
@@ -518,6 +557,9 @@ func (h *PaymentHandler) GetPayWays(c *gin.Context) {
 | 
			
		||||
	if h.App.Config.JPayConfig.Enabled {
 | 
			
		||||
		data["payjs"] = gin.H{"name": h.App.Config.JPayConfig.Name}
 | 
			
		||||
	}
 | 
			
		||||
	if h.App.Config.WechatPayConfig.Enabled {
 | 
			
		||||
		data["wechat"] = gin.H{"name": "wechat"}
 | 
			
		||||
	}
 | 
			
		||||
	resp.SUCCESS(c, data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -584,7 +626,7 @@ func (h *PaymentHandler) PayJsNotify(c *gin.Context) {
 | 
			
		||||
 | 
			
		||||
	orderNo := c.Request.Form.Get("out_trade_no")
 | 
			
		||||
	returnCode := c.Request.Form.Get("return_code")
 | 
			
		||||
	logger.Infof("收到订单支付回调,订单 NO:%s,支付结果代码:%v", orderNo, returnCode)
 | 
			
		||||
	logger.Infof("收到PayJs订单支付回调,订单 NO:%s,支付结果代码:%v", orderNo, returnCode)
 | 
			
		||||
	// 支付失败
 | 
			
		||||
	if returnCode != "1" {
 | 
			
		||||
		return
 | 
			
		||||
@@ -592,7 +634,7 @@ func (h *PaymentHandler) PayJsNotify(c *gin.Context) {
 | 
			
		||||
 | 
			
		||||
	// 校验订单支付状态
 | 
			
		||||
	tradeNo := c.Request.Form.Get("payjs_order_id")
 | 
			
		||||
	err = h.js.Check(tradeNo)
 | 
			
		||||
	err = h.jsPayService.TradeVerify(tradeNo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Error("订单校验失败:", err)
 | 
			
		||||
		c.String(http.StatusOK, "fail")
 | 
			
		||||
@@ -607,3 +649,30 @@ func (h *PaymentHandler) PayJsNotify(c *gin.Context) {
 | 
			
		||||
 | 
			
		||||
	c.String(http.StatusOK, "success")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WechatPayNotify 微信商户支付异步回调
 | 
			
		||||
func (h *PaymentHandler) WechatPayNotify(c *gin.Context) {
 | 
			
		||||
	err := c.Request.ParseForm()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		c.String(http.StatusOK, "fail")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result := h.wechatPayService.TradeVerify(c.Request)
 | 
			
		||||
	if !result.Success() {
 | 
			
		||||
		logger.Error("订单校验失败:", err)
 | 
			
		||||
		c.JSON(http.StatusBadRequest, gin.H{
 | 
			
		||||
			"code":    "FAIL",
 | 
			
		||||
			"message": err.Error(),
 | 
			
		||||
		})
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = h.notify(result.OutTradeNo, result.TradeId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		c.String(http.StatusOK, "fail")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.String(http.StatusOK, "success")
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,9 @@ import (
 | 
			
		||||
type TestHandler struct {
 | 
			
		||||
	db        *gorm.DB
 | 
			
		||||
	snowflake *service.Snowflake
 | 
			
		||||
	js        *payment.PayJS
 | 
			
		||||
	js        *payment.JPayService
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewTestHandler(db *gorm.DB, snowflake *service.Snowflake, js *payment.PayJS) *TestHandler {
 | 
			
		||||
func NewTestHandler(db *gorm.DB, snowflake *service.Snowflake, js *payment.JPayService) *TestHandler {
 | 
			
		||||
	return &TestHandler{db: db, snowflake: snowflake, js: js}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -211,7 +211,8 @@ func main() {
 | 
			
		||||
 | 
			
		||||
		fx.Provide(payment.NewAlipayService),
 | 
			
		||||
		fx.Provide(payment.NewHuPiPay),
 | 
			
		||||
		fx.Provide(payment.NewPayJS),
 | 
			
		||||
		fx.Provide(payment.NewJPayService),
 | 
			
		||||
		fx.Provide(payment.NewWechatService),
 | 
			
		||||
		fx.Provide(service.NewSnowflake),
 | 
			
		||||
		fx.Provide(service.NewXXLJobExecutor),
 | 
			
		||||
		fx.Invoke(func(exec *service.XXLJobExecutor, config *types.AppConfig) {
 | 
			
		||||
@@ -373,6 +374,7 @@ func main() {
 | 
			
		||||
			group.POST("alipay/notify", h.AlipayNotify)
 | 
			
		||||
			group.POST("hupipay/notify", h.HuPiPayNotify)
 | 
			
		||||
			group.POST("payjs/notify", h.PayJsNotify)
 | 
			
		||||
			group.POST("wechat/notify", h.WechatPayNotify)
 | 
			
		||||
		}),
 | 
			
		||||
		fx.Invoke(func(s *core.AppServer, h *admin.ProductHandler) {
 | 
			
		||||
			group := s.Engine.Group("/api/admin/product/")
 | 
			
		||||
 
 | 
			
		||||
@@ -41,8 +41,7 @@ func NewAlipayService(appConfig *types.AppConfig) (*AlipayService, error) {
 | 
			
		||||
		return nil, fmt.Errorf("error with initialize alipay service: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	client.DebugSwitch = gopay.DebugOn
 | 
			
		||||
 | 
			
		||||
	//client.DebugSwitch = gopay.DebugOn // 开启调试模式
 | 
			
		||||
	client.SetLocation(alipay.LocationShanghai). // 设置时区,不设置或出错均为默认服务器时间
 | 
			
		||||
		SetCharset(alipay.UTF8). // 设置字符编码,不设置默认 utf-8
 | 
			
		||||
		SetSignType(alipay.RSA2). // 设置签名类型,不设置默认 RSA2
 | 
			
		||||
@@ -56,12 +55,12 @@ func NewAlipayService(appConfig *types.AppConfig) (*AlipayService, error) {
 | 
			
		||||
	return &AlipayService{config: &config, client: client}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *AlipayService) PayUrlMobile(outTradeNo string, Amount string, subject string) (string, error) {
 | 
			
		||||
func (s *AlipayService) PayUrlMobile(outTradeNo string, amount string, subject string) (string, error) {
 | 
			
		||||
	bm := make(gopay.BodyMap)
 | 
			
		||||
	bm.Set("subject", subject)
 | 
			
		||||
	bm.Set("out_trade_no", outTradeNo)
 | 
			
		||||
	bm.Set("quit_url", s.config.ReturnURL)
 | 
			
		||||
	bm.Set("total_amount", Amount)
 | 
			
		||||
	bm.Set("total_amount", amount)
 | 
			
		||||
	bm.Set("product_code", "QUICK_WAP_WAY")
 | 
			
		||||
	return s.client.TradeWapPay(context.Background(), bm)
 | 
			
		||||
}
 | 
			
		||||
@@ -80,7 +79,7 @@ func (s *AlipayService) TradeVerify(request *http.Request) NotifyVo {
 | 
			
		||||
	notifyReq, err := alipay.ParseNotifyToBodyMap(request) // c.Request 是 gin 框架的写法
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return NotifyVo{
 | 
			
		||||
			Status:  0,
 | 
			
		||||
			Status:  Failure,
 | 
			
		||||
			Message: "error with parse notify request: " + err.Error(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -88,7 +87,7 @@ func (s *AlipayService) TradeVerify(request *http.Request) NotifyVo {
 | 
			
		||||
	_, err = alipay.VerifySignWithCert(s.config.AlipayPublicKey, notifyReq)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return NotifyVo{
 | 
			
		||||
			Status:  0,
 | 
			
		||||
			Status:  Failure,
 | 
			
		||||
			Message: "error with verify sign: " + err.Error(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -104,23 +103,23 @@ func (s *AlipayService) TradeQuery(outTradeNo string) NotifyVo {
 | 
			
		||||
	rsp, err := s.client.TradeQuery(context.Background(), bm)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return NotifyVo{
 | 
			
		||||
			Status:  0,
 | 
			
		||||
			Status:  Failure,
 | 
			
		||||
			Message: "异步查询验证订单信息发生错误" + outTradeNo + err.Error(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if rsp.Response.TradeStatus == "TRADE_SUCCESS" {
 | 
			
		||||
		return NotifyVo{
 | 
			
		||||
			Status:     1,
 | 
			
		||||
			Status:     Success,
 | 
			
		||||
			OutTradeNo: rsp.Response.OutTradeNo,
 | 
			
		||||
			TradeNo:    rsp.Response.TradeNo,
 | 
			
		||||
			TradeId:    rsp.Response.TradeNo,
 | 
			
		||||
			Amount:     rsp.Response.TotalAmount,
 | 
			
		||||
			Subject:    rsp.Response.Subject,
 | 
			
		||||
			Message:    "OK",
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		return NotifyVo{
 | 
			
		||||
			Status:  0,
 | 
			
		||||
			Status:  Failure,
 | 
			
		||||
			Message: "异步查询验证订单信息发生错误" + outTradeNo,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -133,16 +132,3 @@ func readKey(filename string) (string, error) {
 | 
			
		||||
	}
 | 
			
		||||
	return string(data), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NotifyVo struct {
 | 
			
		||||
	Status     int
 | 
			
		||||
	OutTradeNo string
 | 
			
		||||
	TradeNo    string
 | 
			
		||||
	Amount     string
 | 
			
		||||
	Message    string
 | 
			
		||||
	Subject    string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v NotifyVo) Success() bool {
 | 
			
		||||
	return v.Status == 1
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,12 +21,12 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type PayJS struct {
 | 
			
		||||
type JPayService struct {
 | 
			
		||||
	config *types.JPayConfig
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewPayJS(appConfig *types.AppConfig) *PayJS {
 | 
			
		||||
	return &PayJS{
 | 
			
		||||
func NewJPayService(appConfig *types.AppConfig) *JPayService {
 | 
			
		||||
	return &JPayService{
 | 
			
		||||
		config: &appConfig.JPayConfig,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -53,7 +53,7 @@ func (r JPayReps) IsOK() bool {
 | 
			
		||||
	return r.ReturnMsg == "SUCCESS"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (js *PayJS) Pay(param JPayReq) JPayReps {
 | 
			
		||||
func (js *JPayService) Pay(param JPayReq) JPayReps {
 | 
			
		||||
	param.NotifyURL = js.config.NotifyURL
 | 
			
		||||
	var p = url.Values{}
 | 
			
		||||
	encode := utils.JsonEncode(param)
 | 
			
		||||
@@ -86,13 +86,13 @@ func (js *PayJS) Pay(param JPayReq) JPayReps {
 | 
			
		||||
	return data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (js *PayJS) PayH5(p url.Values) string {
 | 
			
		||||
func (js *JPayService) PayH5(p url.Values) string {
 | 
			
		||||
	p.Add("mchid", js.config.AppId)
 | 
			
		||||
	p.Add("sign", js.sign(p))
 | 
			
		||||
	return fmt.Sprintf("%s/api/cashier?%s", js.config.ApiURL, p.Encode())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (js *PayJS) sign(params url.Values) string {
 | 
			
		||||
func (js *JPayService) sign(params url.Values) string {
 | 
			
		||||
	params.Del(`sign`)
 | 
			
		||||
	var keys = make([]string, 0, 0)
 | 
			
		||||
	for key := range params {
 | 
			
		||||
@@ -117,20 +117,18 @@ func (js *PayJS) sign(params url.Values) string {
 | 
			
		||||
	return strings.ToUpper(md5res)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check 查询订单支付状态
 | 
			
		||||
// TradeVerify 查询订单支付状态
 | 
			
		||||
// @param tradeNo 支付平台交易 ID
 | 
			
		||||
func (js *PayJS) Check(tradeNo string) error {
 | 
			
		||||
func (js *JPayService) TradeVerify(tradeNo string) error {
 | 
			
		||||
	apiURL := fmt.Sprintf("%s/api/check", js.config.ApiURL)
 | 
			
		||||
	params := url.Values{}
 | 
			
		||||
	params.Add("payjs_order_id", tradeNo)
 | 
			
		||||
	params.Add("sign", js.sign(params))
 | 
			
		||||
	data := strings.NewReader(params.Encode())
 | 
			
		||||
	resp, err := http.Post(apiURL, "application/x-www-form-urlencoded", data)
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("error with http reqeust: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
	body, err := io.ReadAll(resp.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								api/service/payment/types.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								api/service/payment/types.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
package payment
 | 
			
		||||
 | 
			
		||||
type NotifyVo struct {
 | 
			
		||||
	Status     int
 | 
			
		||||
	OutTradeNo string // 商户订单号
 | 
			
		||||
	TradeId    string // 交易ID
 | 
			
		||||
	Amount     string // 交易金额
 | 
			
		||||
	Message    string
 | 
			
		||||
	Subject    string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v NotifyVo) Success() bool {
 | 
			
		||||
	return v.Status == Success
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	Success = 0
 | 
			
		||||
	Failure = 1
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										135
									
								
								api/service/payment/wepay_service.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								api/service/payment/wepay_service.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
package payment
 | 
			
		||||
 | 
			
		||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 | 
			
		||||
// * Copyright 2023 The Geek-AI Authors. All rights reserved.
 | 
			
		||||
// * Use of this source code is governed by a Apache-2.0 license
 | 
			
		||||
// * that can be found in the LICENSE file.
 | 
			
		||||
// * @Author yangjian102621@163.com
 | 
			
		||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"geekai/core/types"
 | 
			
		||||
	"github.com/go-pay/gopay"
 | 
			
		||||
	"github.com/go-pay/gopay/wechat/v3"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type WechatPayService struct {
 | 
			
		||||
	config *types.WechatPayConfig
 | 
			
		||||
	client *wechat.ClientV3
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewWechatService(appConfig *types.AppConfig) (*WechatPayService, error) {
 | 
			
		||||
	config := appConfig.WechatPayConfig
 | 
			
		||||
	if !config.Enabled {
 | 
			
		||||
		logger.Info("Disabled WechatPay service")
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	priKey, err := readKey(config.PrivateKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("error with read App Private key: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	client, err := wechat.NewClientV3(config.MchId, config.SerialNo, config.ApiV3Key, priKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("error with initialize WechatPay service: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	err = client.AutoVerifySign()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("error with autoVerifySign: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	//client.DebugSwitch = gopay.DebugOn
 | 
			
		||||
 | 
			
		||||
	return &WechatPayService{config: &config, client: client}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *WechatPayService) PayUrlNative(outTradeNo string, amount int, subject string) (string, error) {
 | 
			
		||||
	expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)
 | 
			
		||||
	// 初始化 BodyMap
 | 
			
		||||
	bm := make(gopay.BodyMap)
 | 
			
		||||
	bm.Set("appid", s.config.AppId).
 | 
			
		||||
		Set("mchid", s.config.MchId).
 | 
			
		||||
		Set("description", subject).
 | 
			
		||||
		Set("out_trade_no", outTradeNo).
 | 
			
		||||
		Set("time_expire", expire).
 | 
			
		||||
		Set("notify_url", s.config.NotifyURL).
 | 
			
		||||
		SetBodyMap("amount", func(bm gopay.BodyMap) {
 | 
			
		||||
			bm.Set("total", amount).
 | 
			
		||||
				Set("currency", "CNY")
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
	wxRsp, err := s.client.V3TransactionNative(context.Background(), bm)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", fmt.Errorf("error with client v3 transaction Native: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	if wxRsp.Code != wechat.Success {
 | 
			
		||||
		return "", fmt.Errorf("error status with generating pay url: %v", wxRsp.Error)
 | 
			
		||||
	}
 | 
			
		||||
	return wxRsp.Response.CodeUrl, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *WechatPayService) PayUrlH5(outTradeNo string, amount int, subject string, ip string) (string, error) {
 | 
			
		||||
	expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)
 | 
			
		||||
	// 初始化 BodyMap
 | 
			
		||||
	bm := make(gopay.BodyMap)
 | 
			
		||||
	bm.Set("appid", s.config.AppId).
 | 
			
		||||
		Set("mchid", s.config.MchId).
 | 
			
		||||
		Set("description", subject).
 | 
			
		||||
		Set("out_trade_no", outTradeNo).
 | 
			
		||||
		Set("time_expire", expire).
 | 
			
		||||
		Set("notify_url", s.config.NotifyURL).
 | 
			
		||||
		SetBodyMap("amount", func(bm gopay.BodyMap) {
 | 
			
		||||
			bm.Set("total", amount).
 | 
			
		||||
				Set("currency", "CNY")
 | 
			
		||||
		}).
 | 
			
		||||
		SetBodyMap("scene_info", func(bm gopay.BodyMap) {
 | 
			
		||||
			bm.Set("payer_client_ip", ip).
 | 
			
		||||
				SetBodyMap("h5_info", func(bm gopay.BodyMap) {
 | 
			
		||||
					bm.Set("type", "Wap")
 | 
			
		||||
				})
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
	wxRsp, err := s.client.V3TransactionH5(context.Background(), bm)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", fmt.Errorf("error with client v3 transaction H5: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	if wxRsp.Code != wechat.Success {
 | 
			
		||||
		return "", fmt.Errorf("error with generating pay url: %v", wxRsp.Error)
 | 
			
		||||
	}
 | 
			
		||||
	return wxRsp.Response.H5Url, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NotifyResponse struct {
 | 
			
		||||
	Code    string `json:"code"`
 | 
			
		||||
	Message string `xml:"message"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TradeVerify 交易验证
 | 
			
		||||
func (s *WechatPayService) TradeVerify(request *http.Request) NotifyVo {
 | 
			
		||||
	notifyReq, err := wechat.V3ParseNotify(request)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return NotifyVo{Status: 1, Message: fmt.Sprintf("error with client v3 parse notify: %v", err)}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO: 这里验签程序有 Bug,一直报错:crypto/rsa: verification error,先暂时取消验签
 | 
			
		||||
	//err = notifyReq.VerifySignByPK(s.client.WxPublicKey())
 | 
			
		||||
	//if err != nil {
 | 
			
		||||
	//	return fmt.Errorf("error with client v3 verify sign: %v", err)
 | 
			
		||||
	//}
 | 
			
		||||
 | 
			
		||||
	// 解密支付密文,验证订单信息
 | 
			
		||||
	result, err := notifyReq.DecryptPayCipherText(s.config.ApiV3Key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return NotifyVo{Status: Failure, Message: fmt.Sprintf("error with client v3 decrypt: %v", err)}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NotifyVo{
 | 
			
		||||
		Status:     Success,
 | 
			
		||||
		OutTradeNo: result.OutTradeNo,
 | 
			
		||||
		TradeId:    result.TransactionId,
 | 
			
		||||
		Amount:     fmt.Sprintf("%.2f", float64(result.Amount.Total)/100),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -2,11 +2,8 @@ package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/url"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	text := "https://nk.img.r9it.com/chatgpt-plus/1712709360012445.png"
 | 
			
		||||
	parse, _ := url.Parse(text)
 | 
			
		||||
	fmt.Println(fmt.Sprintf("%s://%s", parse.Scheme, parse.Host))
 | 
			
		||||
	fmt.Println(fmt.Sprintf("%v", float64(90)/100))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
VUE_APP_API_HOST=http://localhost:5678
 | 
			
		||||
VUE_APP_WS_HOST=ws://localhost:5678
 | 
			
		||||
VUE_APP_API_HOST=http://172.22.11.69:5678
 | 
			
		||||
VUE_APP_WS_HOST=ws://172.22.11.69:5678
 | 
			
		||||
VUE_APP_USER=18575670125
 | 
			
		||||
VUE_APP_PASS=12345678
 | 
			
		||||
VUE_APP_ADMIN_USER=admin
 | 
			
		||||
 
 | 
			
		||||
@@ -96,6 +96,9 @@ onMounted(() => {
 | 
			
		||||
    if (res.data.rand_bg) {
 | 
			
		||||
      bgClass.value = "rand-bg"
 | 
			
		||||
    }
 | 
			
		||||
    if (res.data.slogan) {
 | 
			
		||||
      slogan.value = res.data.slogan
 | 
			
		||||
    }
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取系统配置失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
 
 | 
			
		||||
@@ -76,6 +76,9 @@
 | 
			
		||||
                    <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>
 | 
			
		||||
                    <el-button type="success" @click="wechatPay(scope.item)" size="small" v-if="payWays['wechat']">
 | 
			
		||||
                      <i class="iconfont icon-wechat-pay"></i> 微信
 | 
			
		||||
                    </el-button>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
@@ -314,6 +317,21 @@ const PayJs = (row) => {
 | 
			
		||||
  genPayQrcode()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const wechatPay = (row) => {
 | 
			
		||||
  payName.value = '微信'
 | 
			
		||||
  curPay.value = "wechat"
 | 
			
		||||
  amount.value = (row.price - row.discount).toFixed(2)
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (row) {
 | 
			
		||||
    curPayProduct.value = row
 | 
			
		||||
  }
 | 
			
		||||
  genPayQrcode()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const queryOrder = (orderNo) => {
 | 
			
		||||
  httpPost("/api/payment/query", {order_no: orderNo}).then(res => {
 | 
			
		||||
    if (res.data.status === 1) {
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,9 @@
 | 
			
		||||
                <el-form-item label="控制台标题" prop="admin_title">
 | 
			
		||||
                  <el-input v-model="system['admin_title']"/>
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="网站Slogan" prop="slogan">
 | 
			
		||||
                  <el-input v-model="system['slogan']"/>
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="网站 LOGO" prop="logo">
 | 
			
		||||
                  <el-input v-model="system['logo']" placeholder="网站LOGO图片">
 | 
			
		||||
                    <template #append>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="index container">
 | 
			
		||||
    <h2 class="title">{{title}}</h2>
 | 
			
		||||
    <van-notice-bar  left-icon="info-o" :scrollable="true">
 | 
			
		||||
      你有多少想象力,AI就有多大创造力。我辈之人,先干为敬,陪您先把 AI 用起来。
 | 
			
		||||
    </van-notice-bar>
 | 
			
		||||
    <van-notice-bar  left-icon="info-o" :scrollable="true">{{slogan}}}</van-notice-bar>
 | 
			
		||||
 | 
			
		||||
    <div class="content">
 | 
			
		||||
      <van-grid :column-num="3" :gutter="10" border>
 | 
			
		||||
@@ -90,8 +88,18 @@ const isLogin = ref(false)
 | 
			
		||||
const apps = ref([])
 | 
			
		||||
const loading = ref(false)
 | 
			
		||||
const roles = ref([])
 | 
			
		||||
const slogan = ref('你有多大想象力,AI就有多大创造力!')
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  httpGet("/api/config/get?key=system").then(res => {
 | 
			
		||||
    title.value = res.data.title
 | 
			
		||||
    if (res.data.slogan) {
 | 
			
		||||
      slogan.value = res.data.slogan
 | 
			
		||||
    }
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取系统配置失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  checkSession().then((user) => {
 | 
			
		||||
    isLogin.value = true
 | 
			
		||||
    roles.value = user.chat_roles
 | 
			
		||||
 
 | 
			
		||||
@@ -69,6 +69,9 @@
 | 
			
		||||
              <van-button type="success" @click="pay('payjs',item)" size="small" v-if="payWays['payjs']">
 | 
			
		||||
                <span><i class="iconfont icon-wechat-pay"></i> 微信</span>
 | 
			
		||||
              </van-button>
 | 
			
		||||
              <van-button type="primary" @click="pay('wechat',item)" size="small" v-if="payWays['wechat']">
 | 
			
		||||
                <i class="iconfont icon-wechat-pay"></i> 微信
 | 
			
		||||
              </van-button>
 | 
			
		||||
            </div>
 | 
			
		||||
          </h4>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user