mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-17 16:56:38 +08:00
wechat payment is ready for PC
This commit is contained in:
parent
ccad7e7bb5
commit
857da34b9c
@ -1,6 +1,7 @@
|
|||||||
# 更新日志
|
# 更新日志
|
||||||
## v4.0.9
|
## v4.0.9
|
||||||
* 环境升级:升级 Golang 到 go1.22.4
|
* 环境升级:升级 Golang 到 go1.22.4
|
||||||
|
* 功能增加:接入微信商户号支付渠道
|
||||||
* Bug修复:修复前端页面菜单把页面撑开,底部留白问题
|
* Bug修复:修复前端页面菜单把页面撑开,底部留白问题
|
||||||
* 功能优化:聊天页面自动根据内容调整输入框的高度
|
* 功能优化:聊天页面自动根据内容调整输入框的高度
|
||||||
* Bug修复:修复Dalle绘图失败退回算力的问题
|
* Bug修复:修复Dalle绘图失败退回算力的问题
|
||||||
|
1
api/.gitignore
vendored
1
api/.gitignore
vendored
@ -18,3 +18,4 @@ data
|
|||||||
config.toml
|
config.toml
|
||||||
static/upload
|
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/alipay/notify" ||
|
||||||
c.Request.URL.Path == "/api/payment/hupipay/notify" ||
|
c.Request.URL.Path == "/api/payment/hupipay/notify" ||
|
||||||
c.Request.URL.Path == "/api/payment/payjs/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/doPay" ||
|
||||||
c.Request.URL.Path == "/api/payment/payWays" ||
|
c.Request.URL.Path == "/api/payment/payWays" ||
|
||||||
strings.HasPrefix(c.Request.URL.Path, "/api/test") ||
|
strings.HasPrefix(c.Request.URL.Path, "/api/test") ||
|
||||||
|
@ -30,10 +30,11 @@ type AppConfig struct {
|
|||||||
SdConfigs []StableDiffusionConfig // sd AI draw service pool
|
SdConfigs []StableDiffusionConfig // sd AI draw service pool
|
||||||
|
|
||||||
XXLConfig XXLConfig
|
XXLConfig XXLConfig
|
||||||
AlipayConfig AlipayConfig
|
AlipayConfig AlipayConfig // 支付宝支付渠道配置
|
||||||
HuPiPayConfig HuPiPayConfig
|
HuPiPayConfig HuPiPayConfig // 虎皮椒支付配置
|
||||||
SmtpConfig SmtpConfig // 邮件发送配置
|
SmtpConfig SmtpConfig // 邮件发送配置
|
||||||
JPayConfig JPayConfig // payjs 支付配置
|
JPayConfig JPayConfig // payjs 支付配置
|
||||||
|
WechatPayConfig WechatPayConfig // 微信支付渠道配置
|
||||||
}
|
}
|
||||||
|
|
||||||
type SmtpConfig struct {
|
type SmtpConfig struct {
|
||||||
@ -85,6 +86,17 @@ type AlipayConfig struct {
|
|||||||
ReturnURL string // 支付成功返回地址
|
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 { //虎皮椒第四方支付配置
|
type HuPiPayConfig struct { //虎皮椒第四方支付配置
|
||||||
Enabled bool // 是否启用该支付通道
|
Enabled bool // 是否启用该支付通道
|
||||||
Name string // 支付名称,如:wechat/alipay
|
Name string // 支付名称,如:wechat/alipay
|
||||||
@ -182,8 +194,9 @@ var QWen = Platform{
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SystemConfig struct {
|
type SystemConfig struct {
|
||||||
Title string `json:"title,omitempty"`
|
Title string `json:"title,omitempty"` // 网站标题
|
||||||
AdminTitle string `json:"admin_title,omitempty"`
|
Slogan string `json:"slogan,omitempty"` // 网站 slogan
|
||||||
|
AdminTitle string `json:"admin_title,omitempty"` // 管理后台标题
|
||||||
Logo string `json:"logo,omitempty"`
|
Logo string `json:"logo,omitempty"`
|
||||||
InitPower int `json:"init_power,omitempty"` // 新用户注册赠送算力值
|
InitPower int `json:"init_power,omitempty"` // 新用户注册赠送算力值
|
||||||
DailyPower int `json:"daily_power,omitempty"` // 每日赠送算力
|
DailyPower int `json:"daily_power,omitempty"` // 每日赠送算力
|
||||||
|
@ -38,6 +38,8 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/go-pay/crypto v0.0.1 // 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/xlog v0.0.2 // indirect
|
||||||
github.com/go-pay/xtime v0.0.2 // indirect
|
github.com/go-pay/xtime v0.0.2 // indirect
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // 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-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 h1:B6InT8CLfSLc6nGRVx9VMJRBBazFMjr293+jl0lLXUY=
|
||||||
github.com/go-pay/crypto v0.0.1/go.mod h1:41oEIvHMKbNcYlWUlRWtsnC6+ASgh7u29z0gJXe5bes=
|
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 h1:rVb+sfv6hiQtknAlZnTTLvU27NvFJ4p0yglN/vPpGXI=
|
||||||
github.com/go-pay/gopay v1.5.101/go.mod h1:AW4Yj8jDZX9BM1/GTLTY1Gy5SHjiq8kQvG5sBTN2sxI=
|
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=
|
github.com/go-pay/util v0.0.2 h1:goJ4f6kNY5zzdtg1Cj8oWC+Cw7bfg/qq2rJangMAb9U=
|
||||||
|
@ -29,10 +29,16 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
type PayWay struct {
|
||||||
PayWayAlipay = "支付宝"
|
Name string `json:"name"`
|
||||||
PayWayXunHu = "虎皮椒"
|
Value string `json:"value"`
|
||||||
PayWayJs = "PayJS"
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
PayWayAlipay = PayWay{Name: "支付宝", Value: "alipay"}
|
||||||
|
PayWayXunHu = PayWay{Name: "虎皮椒", Value: "hupi"}
|
||||||
|
PayWayJs = PayWay{Name: "PayJS", Value: "payjs"}
|
||||||
|
PayWayWechat = PayWay{Name: "微信支付", Value: "wechat"}
|
||||||
)
|
)
|
||||||
|
|
||||||
// PaymentHandler 支付服务回调 handler
|
// PaymentHandler 支付服务回调 handler
|
||||||
@ -40,7 +46,8 @@ type PaymentHandler struct {
|
|||||||
BaseHandler
|
BaseHandler
|
||||||
alipayService *payment.AlipayService
|
alipayService *payment.AlipayService
|
||||||
huPiPayService *payment.HuPiPayService
|
huPiPayService *payment.HuPiPayService
|
||||||
js *payment.PayJS
|
jsPayService *payment.JPayService
|
||||||
|
wechatPayService *payment.WechatPayService
|
||||||
snowflake *service.Snowflake
|
snowflake *service.Snowflake
|
||||||
fs embed.FS
|
fs embed.FS
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
@ -51,14 +58,16 @@ func NewPaymentHandler(
|
|||||||
server *core.AppServer,
|
server *core.AppServer,
|
||||||
alipayService *payment.AlipayService,
|
alipayService *payment.AlipayService,
|
||||||
huPiPayService *payment.HuPiPayService,
|
huPiPayService *payment.HuPiPayService,
|
||||||
js *payment.PayJS,
|
jsPayService *payment.JPayService,
|
||||||
|
wechatPayService *payment.WechatPayService,
|
||||||
db *gorm.DB,
|
db *gorm.DB,
|
||||||
snowflake *service.Snowflake,
|
snowflake *service.Snowflake,
|
||||||
fs embed.FS) *PaymentHandler {
|
fs embed.FS) *PaymentHandler {
|
||||||
return &PaymentHandler{
|
return &PaymentHandler{
|
||||||
alipayService: alipayService,
|
alipayService: alipayService,
|
||||||
huPiPayService: huPiPayService,
|
huPiPayService: huPiPayService,
|
||||||
js: js,
|
jsPayService: jsPayService,
|
||||||
|
wechatPayService: wechatPayService,
|
||||||
snowflake: snowflake,
|
snowflake: snowflake,
|
||||||
fs: fs,
|
fs: fs,
|
||||||
lock: sync.Mutex{},
|
lock: sync.Mutex{},
|
||||||
@ -108,10 +117,9 @@ func (h *PaymentHandler) DoPay(c *gin.Context) {
|
|||||||
|
|
||||||
// 更新扫码状态
|
// 更新扫码状态
|
||||||
h.DB.Model(&order).UpdateColumn("status", types.OrderScanned)
|
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)
|
uri, err := h.alipayService.PayUrlMobile(order.OrderNo, amount, order.Subject)
|
||||||
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())
|
||||||
@ -212,14 +220,21 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
|
|||||||
var notifyURL string
|
var notifyURL string
|
||||||
switch data.PayWay {
|
switch data.PayWay {
|
||||||
case "hupi":
|
case "hupi":
|
||||||
payWay = PayWayXunHu
|
payWay = PayWayXunHu.Value
|
||||||
notifyURL = h.App.Config.HuPiPayConfig.NotifyURL
|
notifyURL = h.App.Config.HuPiPayConfig.NotifyURL
|
||||||
|
break
|
||||||
case "payjs":
|
case "payjs":
|
||||||
payWay = PayWayJs
|
payWay = PayWayJs.Value
|
||||||
notifyURL = h.App.Config.JPayConfig.NotifyURL
|
notifyURL = h.App.Config.JPayConfig.NotifyURL
|
||||||
default:
|
break
|
||||||
payWay = PayWayAlipay
|
case "alipay":
|
||||||
|
payWay = PayWayAlipay.Value
|
||||||
notifyURL = h.App.Config.AlipayConfig.NotifyURL
|
notifyURL = h.App.Config.AlipayConfig.NotifyURL
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
payWay = PayWayWechat.Value
|
||||||
|
notifyURL = h.App.Config.WechatPayConfig.NotifyURL
|
||||||
|
|
||||||
}
|
}
|
||||||
// 创建订单
|
// 创建订单
|
||||||
remark := types.OrderRemark{
|
remark := types.OrderRemark{
|
||||||
@ -255,7 +270,7 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
|
|||||||
OutTradeNo: order.OrderNo,
|
OutTradeNo: order.OrderNo,
|
||||||
Subject: product.Name,
|
Subject: product.Name,
|
||||||
}
|
}
|
||||||
r := h.js.Pay(params)
|
r := h.jsPayService.Pay(params)
|
||||||
if r.IsOK() {
|
if r.IsOK() {
|
||||||
resp.SUCCESS(c, gin.H{"order_no": order.OrderNo, "image": r.Qrcode})
|
resp.SUCCESS(c, gin.H{"order_no": order.OrderNo, "image": r.Qrcode})
|
||||||
return
|
return
|
||||||
@ -274,6 +289,8 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
|
|||||||
} else {
|
} else {
|
||||||
logo = "res/img/alipay.jpg"
|
logo = "res/img/alipay.jpg"
|
||||||
}
|
}
|
||||||
|
} else if data.PayWay == "wechat" {
|
||||||
|
logo = "res/img/wechat-pay.jpg"
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := h.fs.Open(logo)
|
file, err := h.fs.Open(logo)
|
||||||
@ -290,7 +307,18 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
|
|||||||
timestamp := time.Now().Unix()
|
timestamp := time.Now().Unix()
|
||||||
signStr := fmt.Sprintf("%s-%s-%d-%s", orderNo, data.PayWay, timestamp, h.signKey)
|
signStr := fmt.Sprintf("%s-%s-%d-%s", orderNo, data.PayWay, timestamp, h.signKey)
|
||||||
sign := utils.Sha256(signStr)
|
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)
|
imgData, err := utils.GenQrcode(imageURL, 400, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.ERROR(c, err.Error())
|
resp.ERROR(c, err.Error())
|
||||||
@ -337,7 +365,7 @@ func (h *PaymentHandler) Mobile(c *gin.Context) {
|
|||||||
var payURL string
|
var payURL string
|
||||||
switch data.PayWay {
|
switch data.PayWay {
|
||||||
case "hupi":
|
case "hupi":
|
||||||
payWay = PayWayXunHu
|
payWay = PayWayXunHu.Name
|
||||||
notifyURL = h.App.Config.HuPiPayConfig.NotifyURL
|
notifyURL = h.App.Config.HuPiPayConfig.NotifyURL
|
||||||
returnURL = h.App.Config.HuPiPayConfig.ReturnURL
|
returnURL = h.App.Config.HuPiPayConfig.ReturnURL
|
||||||
parse, _ := url.Parse(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)
|
r, err := h.huPiPayService.Pay(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("error with generating Pay URL: ", err.Error())
|
errMsg := "error with generating Pay Hupi URL: " + err.Error()
|
||||||
resp.ERROR(c, "error with generating Pay URL: "+err.Error())
|
logger.Error(errMsg)
|
||||||
|
resp.ERROR(c, errMsg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
payURL = r.URL
|
payURL = r.URL
|
||||||
case "payjs":
|
case "payjs":
|
||||||
payWay = PayWayJs
|
payWay = PayWayJs.Name
|
||||||
notifyURL = h.App.Config.JPayConfig.NotifyURL
|
notifyURL = h.App.Config.JPayConfig.NotifyURL
|
||||||
returnURL = h.App.Config.JPayConfig.ReturnURL
|
returnURL = h.App.Config.JPayConfig.ReturnURL
|
||||||
totalFee := decimal.NewFromFloat(product.Price).Sub(decimal.NewFromFloat(product.Discount)).Mul(decimal.NewFromInt(100)).IntPart()
|
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("body", product.Name)
|
||||||
params.Add("notify_url", notifyURL)
|
params.Add("notify_url", notifyURL)
|
||||||
params.Add("auto", "0")
|
params.Add("auto", "0")
|
||||||
payURL = h.js.PayH5(params)
|
payURL = h.jsPayService.PayH5(params)
|
||||||
case "alipay":
|
case "alipay":
|
||||||
payWay = PayWayAlipay
|
payWay = PayWayAlipay.Name
|
||||||
payURL, err = h.alipayService.PayUrlMobile(orderNo, fmt.Sprintf("%.2f", amount), product.Name)
|
payURL, err = h.alipayService.PayUrlMobile(orderNo, fmt.Sprintf("%.2f", amount), product.Name)
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -518,6 +557,9 @@ func (h *PaymentHandler) GetPayWays(c *gin.Context) {
|
|||||||
if h.App.Config.JPayConfig.Enabled {
|
if h.App.Config.JPayConfig.Enabled {
|
||||||
data["payjs"] = gin.H{"name": h.App.Config.JPayConfig.Name}
|
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)
|
resp.SUCCESS(c, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,7 +626,7 @@ func (h *PaymentHandler) PayJsNotify(c *gin.Context) {
|
|||||||
|
|
||||||
orderNo := c.Request.Form.Get("out_trade_no")
|
orderNo := c.Request.Form.Get("out_trade_no")
|
||||||
returnCode := c.Request.Form.Get("return_code")
|
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" {
|
if returnCode != "1" {
|
||||||
return
|
return
|
||||||
@ -592,7 +634,7 @@ func (h *PaymentHandler) PayJsNotify(c *gin.Context) {
|
|||||||
|
|
||||||
// 校验订单支付状态
|
// 校验订单支付状态
|
||||||
tradeNo := c.Request.Form.Get("payjs_order_id")
|
tradeNo := c.Request.Form.Get("payjs_order_id")
|
||||||
err = h.js.Check(tradeNo)
|
err = h.jsPayService.TradeVerify(tradeNo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("订单校验失败:", err)
|
logger.Error("订单校验失败:", err)
|
||||||
c.String(http.StatusOK, "fail")
|
c.String(http.StatusOK, "fail")
|
||||||
@ -607,3 +649,30 @@ func (h *PaymentHandler) PayJsNotify(c *gin.Context) {
|
|||||||
|
|
||||||
c.String(http.StatusOK, "success")
|
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 {
|
type TestHandler struct {
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
snowflake *service.Snowflake
|
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}
|
return &TestHandler{db: db, snowflake: snowflake, js: js}
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,8 @@ func main() {
|
|||||||
|
|
||||||
fx.Provide(payment.NewAlipayService),
|
fx.Provide(payment.NewAlipayService),
|
||||||
fx.Provide(payment.NewHuPiPay),
|
fx.Provide(payment.NewHuPiPay),
|
||||||
fx.Provide(payment.NewPayJS),
|
fx.Provide(payment.NewJPayService),
|
||||||
|
fx.Provide(payment.NewWechatService),
|
||||||
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) {
|
||||||
@ -373,6 +374,7 @@ func main() {
|
|||||||
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)
|
group.POST("payjs/notify", h.PayJsNotify)
|
||||||
|
group.POST("wechat/notify", h.WechatPayNotify)
|
||||||
}),
|
}),
|
||||||
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/")
|
||||||
|
@ -41,8 +41,7 @@ func NewAlipayService(appConfig *types.AppConfig) (*AlipayService, error) {
|
|||||||
return nil, fmt.Errorf("error with initialize alipay service: %v", err)
|
return nil, fmt.Errorf("error with initialize alipay service: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client.DebugSwitch = gopay.DebugOn
|
//client.DebugSwitch = gopay.DebugOn // 开启调试模式
|
||||||
|
|
||||||
client.SetLocation(alipay.LocationShanghai). // 设置时区,不设置或出错均为默认服务器时间
|
client.SetLocation(alipay.LocationShanghai). // 设置时区,不设置或出错均为默认服务器时间
|
||||||
SetCharset(alipay.UTF8). // 设置字符编码,不设置默认 utf-8
|
SetCharset(alipay.UTF8). // 设置字符编码,不设置默认 utf-8
|
||||||
SetSignType(alipay.RSA2). // 设置签名类型,不设置默认 RSA2
|
SetSignType(alipay.RSA2). // 设置签名类型,不设置默认 RSA2
|
||||||
@ -56,12 +55,12 @@ func NewAlipayService(appConfig *types.AppConfig) (*AlipayService, error) {
|
|||||||
return &AlipayService{config: &config, client: client}, nil
|
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 := make(gopay.BodyMap)
|
||||||
bm.Set("subject", subject)
|
bm.Set("subject", subject)
|
||||||
bm.Set("out_trade_no", outTradeNo)
|
bm.Set("out_trade_no", outTradeNo)
|
||||||
bm.Set("quit_url", s.config.ReturnURL)
|
bm.Set("quit_url", s.config.ReturnURL)
|
||||||
bm.Set("total_amount", Amount)
|
bm.Set("total_amount", amount)
|
||||||
bm.Set("product_code", "QUICK_WAP_WAY")
|
bm.Set("product_code", "QUICK_WAP_WAY")
|
||||||
return s.client.TradeWapPay(context.Background(), bm)
|
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 框架的写法
|
notifyReq, err := alipay.ParseNotifyToBodyMap(request) // c.Request 是 gin 框架的写法
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NotifyVo{
|
return NotifyVo{
|
||||||
Status: 0,
|
Status: Failure,
|
||||||
Message: "error with parse notify request: " + err.Error(),
|
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)
|
_, err = alipay.VerifySignWithCert(s.config.AlipayPublicKey, notifyReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NotifyVo{
|
return NotifyVo{
|
||||||
Status: 0,
|
Status: Failure,
|
||||||
Message: "error with verify sign: " + err.Error(),
|
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)
|
rsp, err := s.client.TradeQuery(context.Background(), bm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NotifyVo{
|
return NotifyVo{
|
||||||
Status: 0,
|
Status: Failure,
|
||||||
Message: "异步查询验证订单信息发生错误" + outTradeNo + err.Error(),
|
Message: "异步查询验证订单信息发生错误" + outTradeNo + err.Error(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if rsp.Response.TradeStatus == "TRADE_SUCCESS" {
|
if rsp.Response.TradeStatus == "TRADE_SUCCESS" {
|
||||||
return NotifyVo{
|
return NotifyVo{
|
||||||
Status: 1,
|
Status: Success,
|
||||||
OutTradeNo: rsp.Response.OutTradeNo,
|
OutTradeNo: rsp.Response.OutTradeNo,
|
||||||
TradeNo: rsp.Response.TradeNo,
|
TradeId: rsp.Response.TradeNo,
|
||||||
Amount: rsp.Response.TotalAmount,
|
Amount: rsp.Response.TotalAmount,
|
||||||
Subject: rsp.Response.Subject,
|
Subject: rsp.Response.Subject,
|
||||||
Message: "OK",
|
Message: "OK",
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return NotifyVo{
|
return NotifyVo{
|
||||||
Status: 0,
|
Status: Failure,
|
||||||
Message: "异步查询验证订单信息发生错误" + outTradeNo,
|
Message: "异步查询验证订单信息发生错误" + outTradeNo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,16 +132,3 @@ func readKey(filename string) (string, error) {
|
|||||||
}
|
}
|
||||||
return string(data), nil
|
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"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PayJS struct {
|
type JPayService struct {
|
||||||
config *types.JPayConfig
|
config *types.JPayConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPayJS(appConfig *types.AppConfig) *PayJS {
|
func NewJPayService(appConfig *types.AppConfig) *JPayService {
|
||||||
return &PayJS{
|
return &JPayService{
|
||||||
config: &appConfig.JPayConfig,
|
config: &appConfig.JPayConfig,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ func (r JPayReps) IsOK() bool {
|
|||||||
return r.ReturnMsg == "SUCCESS"
|
return r.ReturnMsg == "SUCCESS"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (js *PayJS) Pay(param JPayReq) JPayReps {
|
func (js *JPayService) Pay(param JPayReq) JPayReps {
|
||||||
param.NotifyURL = js.config.NotifyURL
|
param.NotifyURL = js.config.NotifyURL
|
||||||
var p = url.Values{}
|
var p = url.Values{}
|
||||||
encode := utils.JsonEncode(param)
|
encode := utils.JsonEncode(param)
|
||||||
@ -86,13 +86,13 @@ func (js *PayJS) Pay(param JPayReq) JPayReps {
|
|||||||
return data
|
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("mchid", js.config.AppId)
|
||||||
p.Add("sign", js.sign(p))
|
p.Add("sign", js.sign(p))
|
||||||
return fmt.Sprintf("%s/api/cashier?%s", js.config.ApiURL, p.Encode())
|
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`)
|
params.Del(`sign`)
|
||||||
var keys = make([]string, 0, 0)
|
var keys = make([]string, 0, 0)
|
||||||
for key := range params {
|
for key := range params {
|
||||||
@ -117,20 +117,18 @@ func (js *PayJS) sign(params url.Values) string {
|
|||||||
return strings.ToUpper(md5res)
|
return strings.ToUpper(md5res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check 查询订单支付状态
|
// TradeVerify 查询订单支付状态
|
||||||
// @param tradeNo 支付平台交易 ID
|
// @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)
|
apiURL := fmt.Sprintf("%s/api/check", js.config.ApiURL)
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
params.Add("payjs_order_id", tradeNo)
|
params.Add("payjs_order_id", tradeNo)
|
||||||
params.Add("sign", js.sign(params))
|
params.Add("sign", js.sign(params))
|
||||||
data := strings.NewReader(params.Encode())
|
data := strings.NewReader(params.Encode())
|
||||||
resp, err := http.Post(apiURL, "application/x-www-form-urlencoded", data)
|
resp, err := http.Post(apiURL, "application/x-www-form-urlencoded", data)
|
||||||
defer resp.Body.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error with http reqeust: %v", err)
|
return fmt.Errorf("error with http reqeust: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := io.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
text := "https://nk.img.r9it.com/chatgpt-plus/1712709360012445.png"
|
fmt.Println(fmt.Sprintf("%v", float64(90)/100))
|
||||||
parse, _ := url.Parse(text)
|
|
||||||
fmt.Println(fmt.Sprintf("%s://%s", parse.Scheme, parse.Host))
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
VUE_APP_API_HOST=http://localhost:5678
|
VUE_APP_API_HOST=http://172.22.11.69:5678
|
||||||
VUE_APP_WS_HOST=ws://localhost:5678
|
VUE_APP_WS_HOST=ws://172.22.11.69:5678
|
||||||
VUE_APP_USER=18575670125
|
VUE_APP_USER=18575670125
|
||||||
VUE_APP_PASS=12345678
|
VUE_APP_PASS=12345678
|
||||||
VUE_APP_ADMIN_USER=admin
|
VUE_APP_ADMIN_USER=admin
|
||||||
|
@ -96,6 +96,9 @@ onMounted(() => {
|
|||||||
if (res.data.rand_bg) {
|
if (res.data.rand_bg) {
|
||||||
bgClass.value = "rand-bg"
|
bgClass.value = "rand-bg"
|
||||||
}
|
}
|
||||||
|
if (res.data.slogan) {
|
||||||
|
slogan.value = res.data.slogan
|
||||||
|
}
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
ElMessage.error("获取系统配置失败:" + e.message)
|
ElMessage.error("获取系统配置失败:" + e.message)
|
||||||
})
|
})
|
||||||
|
@ -76,6 +76,9 @@
|
|||||||
<el-button type="success" @click="PayJs(scope.item)" size="small" v-if="payWays['payjs']">
|
<el-button type="success" @click="PayJs(scope.item)" size="small" v-if="payWays['payjs']">
|
||||||
<span><i class="iconfont icon-wechat-pay"></i> 微信</span>
|
<span><i class="iconfont icon-wechat-pay"></i> 微信</span>
|
||||||
</el-button>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -314,6 +317,21 @@ const PayJs = (row) => {
|
|||||||
genPayQrcode()
|
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) => {
|
const queryOrder = (orderNo) => {
|
||||||
httpPost("/api/payment/query", {order_no: orderNo}).then(res => {
|
httpPost("/api/payment/query", {order_no: orderNo}).then(res => {
|
||||||
if (res.data.status === 1) {
|
if (res.data.status === 1) {
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
<el-form-item label="控制台标题" prop="admin_title">
|
<el-form-item label="控制台标题" prop="admin_title">
|
||||||
<el-input v-model="system['admin_title']"/>
|
<el-input v-model="system['admin_title']"/>
|
||||||
</el-form-item>
|
</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-form-item label="网站 LOGO" prop="logo">
|
||||||
<el-input v-model="system['logo']" placeholder="网站LOGO图片">
|
<el-input v-model="system['logo']" placeholder="网站LOGO图片">
|
||||||
<template #append>
|
<template #append>
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="index container">
|
<div class="index container">
|
||||||
<h2 class="title">{{title}}</h2>
|
<h2 class="title">{{title}}</h2>
|
||||||
<van-notice-bar left-icon="info-o" :scrollable="true">
|
<van-notice-bar left-icon="info-o" :scrollable="true">{{slogan}}}</van-notice-bar>
|
||||||
你有多少想象力,AI就有多大创造力。我辈之人,先干为敬,陪您先把 AI 用起来。
|
|
||||||
</van-notice-bar>
|
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<van-grid :column-num="3" :gutter="10" border>
|
<van-grid :column-num="3" :gutter="10" border>
|
||||||
@ -90,8 +88,18 @@ const isLogin = ref(false)
|
|||||||
const apps = ref([])
|
const apps = ref([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const roles = ref([])
|
const roles = ref([])
|
||||||
|
const slogan = ref('你有多大想象力,AI就有多大创造力!')
|
||||||
|
|
||||||
onMounted(() => {
|
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) => {
|
checkSession().then((user) => {
|
||||||
isLogin.value = true
|
isLogin.value = true
|
||||||
roles.value = user.chat_roles
|
roles.value = user.chat_roles
|
||||||
|
@ -69,6 +69,9 @@
|
|||||||
<van-button type="success" @click="pay('payjs',item)" size="small" v-if="payWays['payjs']">
|
<van-button type="success" @click="pay('payjs',item)" size="small" v-if="payWays['payjs']">
|
||||||
<span><i class="iconfont icon-wechat-pay"></i> 微信</span>
|
<span><i class="iconfont icon-wechat-pay"></i> 微信</span>
|
||||||
</van-button>
|
</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>
|
</div>
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user