This commit is contained in:
2024-09-14 10:48:09 +08:00
commit a5fa833937
192 changed files with 87641 additions and 0 deletions

68
core/logger.go Normal file
View File

@@ -0,0 +1,68 @@
package core
import (
"bytes"
"fmt"
"github.com/gin-gonic/gin"
"gopkg.in/natefinch/lumberjack.v2"
"io/ioutil"
"log"
"path/filepath"
"time"
)
func SetupLogger() *lumberjack.Logger {
// 获取当前日期
now := time.Now()
month := now.Format("2006-01")
day := now.Format("2006-01-02")
// 日志文件路径
logFilePath := filepath.Join("./logs", month, day)
// 配置 lumberjack 日志轮转
logger := &lumberjack.Logger{
Filename: logFilePath,
MaxSize: 1, // 日志文件最大尺寸为100MB
MaxBackups: 30, // 最多保留30个备份文件
MaxAge: 30, // 日志文件最多保留30天
Compress: false, // 启用压缩
}
return logger
}
func LoggingMiddleware(logger *lumberjack.Logger) gin.HandlerFunc {
return func(c *gin.Context) {
// 记录开始时间
startTime := time.Now()
// 获取请求方法
method := c.Request.Method
// 获取GET参数
getParams := c.Request.URL.Query()
// 获取其他请求方法的参数
var bodyBytes []byte
if c.Request.Body != nil {
bodyBytes, _ = ioutil.ReadAll(c.Request.Body)
}
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) // 还原请求Body
// 打印日志
logEntry := fmt.Sprintf("Start: %s, Method: %s, URL: %s, GET params: %v, Body: %s",
startTime.Format(time.RFC3339), method, c.Request.URL, getParams, string(bodyBytes))
log.SetOutput(logger)
log.Println(logEntry)
// 处理请求
c.Next()
// 记录结束时间
endTime := time.Now()
logEntry = fmt.Sprintf("End: %s, Method: %s, URL: %s, Status: %d, Latency: %s",
endTime.Format(time.RFC3339), method, c.Request.URL, c.Writer.Status(), endTime.Sub(startTime))
log.Println(logEntry)
}
}

76
core/pay.go Normal file
View File

@@ -0,0 +1,76 @@
package core
import (
"context"
"fmt"
"github.com/smartwalle/alipay/v3"
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
"github.com/wechatpay-apiv3/wechatpay-go/services/certificates"
"github.com/wechatpay-apiv3/wechatpay-go/utils"
"log"
"qnc-server/config"
"qnc-server/global"
"qnc-server/model/model"
"qnc-server/service"
)
var orderService = service.OrderService{}
func InitWeChatPay(mchID string, mchCertificateSerialNumber string, mchAPIv3Key string, privateKeyPath string) *core.Client {
mchPrivateKey, err := utils.LoadPrivateKeyWithPath(privateKeyPath)
if err != nil {
log.Fatal("load merchant private key error")
}
ctx := context.Background()
// 使用商户私钥等初始化 client并使它具有自动定时获取微信支付平台证书的能力
opts := []core.ClientOption{
option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
}
client, err := core.NewClient(ctx, opts...)
if err != nil {
log.Fatalf("new wechat pay client err:%s", err)
}
// 发送请求,以下载微信支付平台证书为例
// https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay5_1.shtml
svc := certificates.CertificatesApiService{Client: client}
resp, result, err := svc.DownloadCertificates(ctx)
log.Printf("status=%d resp=%s", result.Response.StatusCode, resp)
return client
}
func InitMPWeChatPay() {
mchID := config.ConfigData.WxPay.MchID
mchCertificateSerialNumber := config.ConfigData.WxPay.MchCertificateSerialNumber
mchAPIv3Key := config.ConfigData.WxPay.MchAPIv3Key
privateKeyPath := "merchant/mp/apiclient_key.pem"
client := InitWeChatPay(mchID, mchCertificateSerialNumber, mchAPIv3Key, privateKeyPath)
global.GlobalData.PayClient = client
orderService.RegisterComplaintNotificationURL(client, model.PlatformMPWEIXIN)
}
func InitMPH5WeChatPay() {
mchID := config.ConfigData.WxPay.MchH5ID
mchCertificateSerialNumber := config.ConfigData.WxPay.MchH5CertificateSerialNumber
mchAPIv3Key := config.ConfigData.WxPay.MchH5APIv3Key
privateKeyPath := "merchant/mph5/apiclient_key.pem"
client := InitWeChatPay(mchID, mchCertificateSerialNumber, mchAPIv3Key, privateKeyPath)
global.GlobalData.PayH5Client = client
orderService.RegisterComplaintNotificationURL(client, model.PlatformH5)
}
func InitAliPay() {
client, err := alipay.New(config.ConfigData.AliPay.AppID, config.ConfigData.AliPay.PrivateKey, true)
if err != nil {
fmt.Println(err)
return
}
err = client.LoadAliPayPublicKey(config.ConfigData.AliPay.PublicKey)
if err != nil {
fmt.Println(err)
return
}
global.GlobalData.AliPayClient = client
fmt.Println("ali pay init success")
log.Println("ali pay init success")
}

54
core/server.go Normal file
View File

@@ -0,0 +1,54 @@
package core
import (
"errors"
"fmt"
"github.com/gin-gonic/gin"
"github.com/unrolled/secure"
"log"
"net/http"
"qnc-server/api"
"qnc-server/config"
)
func RunServer() {
// 设置日志文件
logger := SetupLogger()
log.SetOutput(logger)
// 设置 Gin 的全局默认输出为日志文件
gin.DefaultWriter = logger
gin.DefaultErrorWriter = logger
//启动 HTTP 服务器
{
rHttp := gin.New()
// 使用自定义的日志中间件
rHttp.LoadHTMLGlob("templates/*")
rHttp.Use(gin.LoggerWithWriter(logger), gin.RecoveryWithWriter(logger), LoggingMiddleware(logger))
api.InitApi(rHttp.Group(config.ConfigData.Server.Prefix))
httpPort := fmt.Sprintf(":%d", config.ConfigData.Server.HttpPort)
log.Printf("HTTP server listening on http://127.0.0.1%s", httpPort)
if err := rHttp.Run(httpPort); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatalf("HTTP server listen error %s", err)
}
}
}
// http重定向到https
func LoadTls() gin.HandlerFunc {
return func(c *gin.Context) {
middleware := secure.New(secure.Options{
SSLRedirect: true,
SSLHost: fmt.Sprintf("localhost:%d", config.ConfigData.Server.HttpsPort),
})
err := middleware.Process(c.Writer, c.Request)
if err != nil {
// 如果出现错误,请不要继续
fmt.Println(err)
return
}
// 继续往下处理
c.Next()
}
}

28
core/viper.go Normal file
View File

@@ -0,0 +1,28 @@
package core
import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
"qnc-server/config"
)
func Viper() {
v := viper.New()
v.SetConfigName("config")
v.SetConfigType("yaml")
v.AddConfigPath(".")
if err := v.ReadInConfig(); err != nil {
panic(fmt.Errorf("fatal error config file: %w", err))
}
v.WatchConfig()
v.OnConfigChange(func(e fsnotify.Event) {
if err := v.Unmarshal(&config.ConfigData); err != nil {
fmt.Println(err)
}
})
if err := v.Unmarshal(&config.ConfigData); err != nil {
panic(fmt.Errorf("unable to decode into struct: %w", err))
}
}