setup.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package handlers
  2. import (
  3. "Wine-Server/utils"
  4. "Wine-Server/utils/tables"
  5. "context"
  6. "database/sql"
  7. "github.com/gin-contrib/cors"
  8. "github.com/gin-gonic/gin"
  9. "github.com/redis/go-redis/v9"
  10. "github.com/wechatpay-apiv3/wechatpay-go/core"
  11. "github.com/wechatpay-apiv3/wechatpay-go/core/auth/verifiers"
  12. "github.com/wechatpay-apiv3/wechatpay-go/core/downloader"
  13. "github.com/wechatpay-apiv3/wechatpay-go/core/notify"
  14. "github.com/wechatpay-apiv3/wechatpay-go/core/option"
  15. "github.com/wechatpay-apiv3/wechatpay-go/services/payments/native"
  16. wx "github.com/wechatpay-apiv3/wechatpay-go/utils"
  17. "log"
  18. "os"
  19. )
  20. type routeFn func(*gin.Engine)
  21. type createTableFn func() error
  22. type App struct {
  23. router *gin.Engine
  24. address string
  25. }
  26. func lostHandler(ctx *gin.Context) {
  27. ctx.JSON(utils.HttpNotFound, utils.Fail("api/resource not found"))
  28. }
  29. func loggerFormat(timeFmt string) gin.HandlerFunc {
  30. return gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
  31. return utils.Format("[wine] %s - %s [%s %s %s] %s, %s %d %s: %s\n",
  32. param.ClientIP,
  33. param.TimeStamp.Format(timeFmt),
  34. param.MethodColor(), param.Method, param.ResetColor(),
  35. param.Path,
  36. param.StatusCodeColor(), param.StatusCode, param.ResetColor(),
  37. param.ErrorMessage,
  38. )
  39. })
  40. }
  41. func CreateApp(config *utils.Config) *App {
  42. if config.Release {
  43. gin.SetMode(gin.ReleaseMode)
  44. } else {
  45. gin.SetMode(gin.DebugMode)
  46. }
  47. utils.Logger = log.New(os.Stderr, "[wine] ", log.Ldate|log.Ltime|log.Lshortfile|log.Lmsgprefix)
  48. initWxPay(config)
  49. initDatabase(config)
  50. router := createRouter(config)
  51. return &App{router: router, address: config.ServerAddr}
  52. }
  53. func (app *App) RouteRegister(routeFns ...routeFn) {
  54. for _, fn := range routeFns {
  55. fn(app.router)
  56. }
  57. }
  58. func (app *App) Start() {
  59. err := app.router.Run(app.address)
  60. if err != nil {
  61. utils.Logger.Printf("server can't run on address[%s] for: %s", app.address, err)
  62. }
  63. }
  64. func initWxPay(config *utils.Config) {
  65. utils.WxTitle, utils.WxV3Key = config.WxPayTitle, config.WxApiV3Key
  66. utils.WxAppId, utils.WxMchId = config.WxAppId, config.WxMerchantAcc
  67. utils.WxCertSeq, utils.WxCertPath = config.WxApiCertSeq, config.WxApiCertPath
  68. var err error
  69. utils.WxPrivateKey, err = wx.LoadPrivateKeyWithPath(config.WxApiCertPath)
  70. if err != nil {
  71. utils.Logger.Fatalf("load merchant private key error: %s\n", err)
  72. }
  73. opts := []core.ClientOption{
  74. option.WithWechatPayAutoAuthCipher(config.WxMerchantAcc, config.WxApiCertSeq, utils.WxPrivateKey, config.WxApiV3Key),
  75. }
  76. utils.WxPayCli = context.Background()
  77. client, err := core.NewClient(utils.WxPayCli, opts...)
  78. if err != nil {
  79. utils.Logger.Fatalf("new wechat pay client error: %s\n", err)
  80. }
  81. utils.WxPaySrv = native.NativeApiService{Client: client}
  82. err = downloader.MgrInstance().RegisterDownloaderWithPrivateKey(
  83. utils.WxPayCli, utils.WxPrivateKey, config.WxApiCertSeq, config.WxMerchantAcc, config.WxApiV3Key,
  84. )
  85. visitor := downloader.MgrInstance().GetCertificateVisitor(config.WxMerchantAcc)
  86. utils.WxCrtHdr, err = notify.NewRSANotifyHandler(config.WxApiV3Key, verifiers.NewSHA256WithRSAVerifier(visitor))
  87. if err != nil {
  88. utils.Logger.Fatalf("wxpay notice handler init error: %s\n", err)
  89. }
  90. }
  91. func initDatabase(config *utils.Config) {
  92. // init
  93. utils.Redis = redis.NewClient(&redis.Options{
  94. Addr: utils.Format("%s:%d", config.RedisHost, config.RedisPort),
  95. Password: config.RedisPass, DB: config.RedisDatabase,
  96. })
  97. db, err := sql.Open(
  98. "mysql",
  99. utils.Format(
  100. "%s:%s@tcp(%s:%d)/%s?loc=Local&charset=utf8&parseTime=true",
  101. config.MysqlUser, config.MysqlPass, config.MysqlHost, config.MysqlPort, config.MysqlDatabase,
  102. ),
  103. )
  104. if err != nil {
  105. utils.Logger.Fatalf("mysql init failed: %s\n", err)
  106. }
  107. err = db.Ping()
  108. if err != nil {
  109. utils.Logger.Fatalf("mysql connection failed: %s\n", err)
  110. }
  111. utils.Mysql = db
  112. // create
  113. toCreate := []createTableFn{
  114. tables.CreateAdvertiseTable, tables.CreateDeviceTable, tables.CreateManagerTable,
  115. tables.CreateParamsTable, tables.CreateVersionTable, tables.CreateWineTable, tables.CreateTradeTable,
  116. }
  117. for _, Fn := range toCreate {
  118. err = Fn()
  119. if err != nil {
  120. utils.Logger.Fatalf("create mysql tables failed: %s\n", err)
  121. }
  122. }
  123. }
  124. func createRouter(config *utils.Config) *gin.Engine {
  125. router := gin.New()
  126. err := router.SetTrustedProxies([]string{"127.0.0.1"})
  127. if err != nil {
  128. utils.Logger.Fatalf("can't trust '127.0.0.1', for: %s", err)
  129. }
  130. if err = utils.LoadRsaKeyPairs(config); err != nil {
  131. utils.Logger.Fatalf("can't generate private and public key.")
  132. }
  133. conf := cors.DefaultConfig()
  134. allow := append(conf.AllowHeaders, "Token", "Device")
  135. conf.AllowAllOrigins, conf.AllowHeaders = true, allow
  136. router.Use(loggerFormat(config.TimeFormat), gin.Recovery(), utils.ErrorHandler, cors.New(conf))
  137. router.NoRoute(lostHandler)
  138. router.Static("/static", "./static")
  139. return router
  140. }