first commit
This commit is contained in:
commit
f258956df7
|
@ -0,0 +1,62 @@
|
|||
# toml配置文件
|
||||
# Wiki:https://github.com/toml-lang/toml
|
||||
ServiceName = "snow"
|
||||
Debug = true
|
||||
Env = "local" # local-本地 develop-开发 beta-预发布 production-线上
|
||||
PrometheusCollectEnable = true
|
||||
SkyWalkingOapServer = "127.0.0.1:11800"
|
||||
|
||||
[Log]
|
||||
Handler = "file"
|
||||
Dir = "./logs"
|
||||
Level = "info"
|
||||
|
||||
[Db]
|
||||
Driver = "mysql"
|
||||
|
||||
[Db.Option]
|
||||
MaxConns = 128
|
||||
MaxIdle = 32
|
||||
IdleTimeout = 180 # second
|
||||
Charset = "utf8mb4"
|
||||
ConnectTimeout = 3 # second
|
||||
|
||||
[Db.Master]
|
||||
Host = "127.0.0.1"
|
||||
Port = 3306
|
||||
User = "root"
|
||||
Password = "123456"
|
||||
DBName = "test"
|
||||
|
||||
[[Db.Slaves]] # 支持多个从库
|
||||
Host = "127.0.0.1"
|
||||
Port = 3306
|
||||
User = "root"
|
||||
Password = "123456"
|
||||
DBName = "test"
|
||||
|
||||
[Api]
|
||||
Host = "0.0.0.0"
|
||||
Port = 8080
|
||||
|
||||
[Cache]
|
||||
Driver = "redis"
|
||||
|
||||
[Redis.Master]
|
||||
Host = "127.0.0.1"
|
||||
Port = 6379
|
||||
#Password = ""
|
||||
#DB = 0
|
||||
|
||||
#[Redis.Option]
|
||||
#MaxIdle = 64
|
||||
#MaxConns = 256
|
||||
#IdleTimeout = 180 # second
|
||||
#ConnectTimeout = 1
|
||||
#ReadTimeout = 1
|
||||
#WriteTimeout = 1
|
||||
|
||||
[AliMns]
|
||||
Url = ""
|
||||
AccessKeyId = ""
|
||||
AccessKeySecret = ""
|
|
@ -0,0 +1,4 @@
|
|||
/.idea
|
||||
/vendor
|
||||
/.env
|
||||
!/.env.example
|
|
@ -0,0 +1,22 @@
|
|||
## Snow
|
||||
Snow是一套简单易用的Go语言业务框架,整体逻辑设计简洁,支持HTTP服务、队列调度和任务调度等常用业务场景模式。
|
||||
|
||||
## Quick start
|
||||
|
||||
### Build
|
||||
sh build/shell/build.sh
|
||||
|
||||
### Run
|
||||
```shell
|
||||
1. build/bin/snow -a api #启动Api服务
|
||||
2. build/bin/snow -a cron #启动Cron定时任务服务
|
||||
3. build/bin/snow -a job #启动队列调度服务
|
||||
4. build/bin/snow -a command -m test #执行名称为test的脚本任务
|
||||
```
|
||||
|
||||
## Documents
|
||||
|
||||
- [项目地址](https://github.com/qit-team/snow)
|
||||
- [中文文档](https://github.com/qit-team/snow/wiki)
|
||||
- [changelog](https://github.com/qit-team/snow/blob/master/CHANGLOG.md)
|
||||
- [xorm](http://gobook.io/read/github.com/go-xorm/manual-zh-CN/)
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
|||
package bannerlistcache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"com.snow.auto_monitor/app/caches"
|
||||
|
||||
"github.com/qit-team/snow-core/cache"
|
||||
)
|
||||
|
||||
const (
|
||||
prefix = caches.BannerList //缓存key的前缀
|
||||
)
|
||||
|
||||
var (
|
||||
instance *bannerListCache
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
type bannerListCache struct {
|
||||
cache.BaseCache
|
||||
}
|
||||
|
||||
//单例模式
|
||||
func GetInstance() *bannerListCache {
|
||||
once.Do(func() {
|
||||
instance = new(bannerListCache)
|
||||
instance.Prefix = prefix
|
||||
//instance.DiName = redis.SingletonMain //设置缓存依赖的实例别名
|
||||
//instance.DriverType = cache.DriverTypeRedis //设置缓存驱动的类型,默认redis
|
||||
//instance.SeTTL(86400) 设置默认缓存时间 默认86400
|
||||
})
|
||||
return instance
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package bannerlistcache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"com.snow.auto_monitor/config"
|
||||
|
||||
"github.com/qit-team/snow-core/cache"
|
||||
_ "github.com/qit-team/snow-core/cache/rediscache"
|
||||
"github.com/qit-team/snow-core/redis"
|
||||
)
|
||||
|
||||
func init() {
|
||||
//加载配置文件
|
||||
conf, err := config.Load("../../../.env")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
//注册redis类
|
||||
err = redis.Pr.Register(cache.DefaultDiName, conf.Redis)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetMulti(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
cache := GetInstance()
|
||||
res, _ := cache.Set(ctx, "1000", "a")
|
||||
if res != true {
|
||||
t.Errorf("set key:%s is error", "1000")
|
||||
}
|
||||
|
||||
keys := []string{"1000", "-2000", "9999"}
|
||||
cacheList, err := cache.GetMulti(ctx, keys...)
|
||||
if err != nil {
|
||||
t.Errorf("getMulti error:%s", err.Error())
|
||||
}
|
||||
fmt.Println(cacheList)
|
||||
i := 0
|
||||
for k, v := range cacheList {
|
||||
i++
|
||||
if k == "1000" {
|
||||
if v != "a" {
|
||||
t.Errorf("value of key:%s is error %v", k, v)
|
||||
}
|
||||
} else {
|
||||
if v != "" {
|
||||
t.Errorf("value of key:%s is error %v", k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
if i != len(keys) {
|
||||
t.Errorf("count of cache key is error: %d", i)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package caches
|
||||
|
||||
//缓存前缀key,不同的业务使用不同的前缀,避免了业务之间的重用冲突
|
||||
const (
|
||||
Cookie = "ck:"
|
||||
Copy = "cp:"
|
||||
BannerList = "bl:"
|
||||
)
|
|
@ -0,0 +1,9 @@
|
|||
package console
|
||||
|
||||
import (
|
||||
"github.com/qit-team/snow-core/command"
|
||||
)
|
||||
|
||||
func RegisterCommand(c *command.Command) {
|
||||
c.AddFunc("test", test)
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package console
|
||||
|
||||
import (
|
||||
"github.com/robfig/cron"
|
||||
)
|
||||
|
||||
/**
|
||||
* 配置执行计划
|
||||
* @wiki https://godoc.org/github.com/robfig/cron
|
||||
*/
|
||||
func RegisterSchedule(c *cron.Cron) {
|
||||
//c.AddFunc("0 30 * * * *", test)
|
||||
//c.AddFunc("@hourly", test)
|
||||
c.AddFunc("@every 10s", test)
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package console
|
||||
|
||||
import "fmt"
|
||||
|
||||
func test() {
|
||||
fmt.Println("run test")
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package common
|
|
@ -0,0 +1,37 @@
|
|||
package errorcode
|
||||
|
||||
const (
|
||||
//成功
|
||||
Success = 200
|
||||
|
||||
//参数错误
|
||||
ParamError = 400
|
||||
|
||||
//未经授权
|
||||
NotAuth = 401
|
||||
|
||||
//请求被禁止
|
||||
Forbidden = 403
|
||||
|
||||
//找不到页面
|
||||
NotFound = 404
|
||||
|
||||
//系统错误
|
||||
SystemError = 500
|
||||
)
|
||||
|
||||
var MsgEN = map[int]string{
|
||||
Success: "success",
|
||||
ParamError: "param error",
|
||||
NotAuth: "not authorized",
|
||||
Forbidden: "forbidden",
|
||||
NotFound: "not found",
|
||||
SystemError: "system error",
|
||||
}
|
||||
|
||||
func GetMsg(code int) string {
|
||||
if msg, ok := MsgEN[code]; ok {
|
||||
return msg
|
||||
}
|
||||
return ""
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package logtype
|
||||
|
||||
const (
|
||||
Message = "message"
|
||||
GoPanic = "go.panic"
|
||||
HTTP = "http"
|
||||
)
|
|
@ -0,0 +1,108 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"com.snow.auto_monitor/app/constants/errorcode"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/qit-team/snow-core/log/logger"
|
||||
"gopkg.in/go-playground/validator.v9"
|
||||
)
|
||||
|
||||
/**
|
||||
* 成功时返回
|
||||
*/
|
||||
func Success(c *gin.Context, data interface{}) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": errorcode.Success,
|
||||
"message": "ok",
|
||||
"request_uri": c.Request.URL.Path,
|
||||
"data": data,
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功时返回
|
||||
*/
|
||||
func SuccessWithList(c *gin.Context, data interface{}, total int64) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": errorcode.Success,
|
||||
"message": "ok",
|
||||
"request_uri": c.Request.URL.Path,
|
||||
"data": gin.H{
|
||||
"list": data,
|
||||
"total": total,
|
||||
},
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败时返回
|
||||
*/
|
||||
func Error(c *gin.Context, code int, msg ...string) {
|
||||
message := ""
|
||||
if len(msg) > 0 {
|
||||
message = msg[0]
|
||||
} else {
|
||||
message = errorcode.GetMsg(code)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": code,
|
||||
"message": message,
|
||||
"request_uri": c.Request.URL.Path,
|
||||
"data": make(map[string]string),
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
func Error404(c *gin.Context) {
|
||||
Error(c, errorcode.NotFound, "路由不存在")
|
||||
}
|
||||
|
||||
func Error500(c *gin.Context) {
|
||||
Error(c, errorcode.SystemError)
|
||||
}
|
||||
|
||||
type HTTPError struct {
|
||||
Code int `json:"code" example:"400"`
|
||||
Message string `json:"message" example:"status bad request"`
|
||||
}
|
||||
|
||||
/**
|
||||
* 将请求的body转换为request数据结构
|
||||
* @param c
|
||||
* @param request 传入request数据结构的指针 如 new(TestRequest)
|
||||
*/
|
||||
func GenRequest(c *gin.Context, request interface{}) (err error) {
|
||||
body, err := ReadBody(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(body, request)
|
||||
if err == nil {
|
||||
validate := validator.New()
|
||||
errValidate := validate.Struct(request)
|
||||
if errValidate != nil {
|
||||
logger.Error(c, "param_validator_exception:"+c.Request.URL.Path, errValidate)
|
||||
return errValidate
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 重复读取body
|
||||
func ReadBody(c *gin.Context) (body []byte, err error) {
|
||||
body, err = ioutil.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
||||
return
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
package merchant
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"com.snow.auto_monitor/app/constants/errorcode"
|
||||
common "com.snow.auto_monitor/app/http/controllers"
|
||||
merEnt "com.snow.auto_monitor/app/http/entities/merchant"
|
||||
merMod "com.snow.auto_monitor/app/models/merchant"
|
||||
merServ "com.snow.auto_monitor/app/services/merchant"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func GetById(c *gin.Context) {
|
||||
request := new(merEnt.GetListByIdReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := merServ.GetById(request.Id)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
var response *merEnt.GetListByIdResp = nil
|
||||
|
||||
if res != nil {
|
||||
|
||||
response = &merEnt.GetListByIdResp{
|
||||
Id: res.Id,
|
||||
Name: res.Name,
|
||||
CreatedAt: res.CreatedAt.Format(time.RFC3339),
|
||||
}
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Search(c *gin.Context) {
|
||||
request := new(merEnt.SearcgReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
start, end := "", ""
|
||||
if len(request.CreatedAt) > 1 {
|
||||
start = request.CreatedAt[0]
|
||||
end = request.CreatedAt[1]
|
||||
}
|
||||
res, err := merServ.Search(
|
||||
request.Id,
|
||||
request.Name,
|
||||
start,
|
||||
end,
|
||||
request.PageSize,
|
||||
request.PageNum,
|
||||
)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
var response []*merEnt.SearchResp = nil
|
||||
|
||||
if len(res) > 0 {
|
||||
for _, item := range res {
|
||||
response = append(response, &merEnt.SearchResp{
|
||||
Id: item.Id,
|
||||
Name: item.Name,
|
||||
CreatedAt: item.CreatedAt.Format(time.RFC3339),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
total, err := merServ.CountAll(
|
||||
request.Id,
|
||||
request.Name,
|
||||
start,
|
||||
end)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
common.SuccessWithList(c, response, total)
|
||||
}
|
||||
|
||||
func Create(c *gin.Context) {
|
||||
request := new(merEnt.CreateReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
merchant := &merMod.Merchant{
|
||||
Name: request.Name,
|
||||
Key: request.Key,
|
||||
}
|
||||
|
||||
affected, err := merServ.Create(merchant)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &merEnt.CreateResp{
|
||||
Id: merchant.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Update(c *gin.Context) {
|
||||
request := new(merEnt.UpdateReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
merchant := &merMod.Merchant{
|
||||
Id: request.Id,
|
||||
Name: request.Name,
|
||||
Key: request.Key,
|
||||
}
|
||||
|
||||
affected, err := merServ.Update(merchant)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &merEnt.UpdateResp{
|
||||
Id: merchant.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Delete(c *gin.Context) {
|
||||
request := new(merEnt.DeleteReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := merServ.Delete(request.Id)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &merEnt.DeleteResp{
|
||||
Id: request.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
package orders
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"com.snow.auto_monitor/app/constants/errorcode"
|
||||
common "com.snow.auto_monitor/app/http/controllers"
|
||||
orderEnt "com.snow.auto_monitor/app/http/entities/orders"
|
||||
orderMod "com.snow.auto_monitor/app/models/orders"
|
||||
orderServ "com.snow.auto_monitor/app/services/orders"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func GetById(c *gin.Context) {
|
||||
request := new(orderEnt.GetListByIdReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
item, err := orderServ.GetById(request.Id)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
var response *orderEnt.GetListByIdResp = nil
|
||||
|
||||
if item != nil {
|
||||
response = &orderEnt.GetListByIdResp{
|
||||
Id: item.Id,
|
||||
OrderNo: item.OrderNo,
|
||||
MerchantId: item.MerchantId,
|
||||
ProductId: item.ProductId,
|
||||
OutTradeNo: item.OutTradeNo,
|
||||
RechargeAccount: item.RechargeAccount,
|
||||
AccountType: item.AccountType,
|
||||
Number: item.Number,
|
||||
NotifyUrl: item.NotifyUrl,
|
||||
ExtendParameter: item.ExtendParameter,
|
||||
Status: item.Status,
|
||||
TransferStatus: item.TransferStatus,
|
||||
CreatedAt: item.CreatedAt.Format(time.RFC3339),
|
||||
}
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Search(c *gin.Context) {
|
||||
request := new(orderEnt.SearchReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
start, end := "", ""
|
||||
if len(request.CreatedAt) > 1 {
|
||||
start = request.CreatedAt[0]
|
||||
end = request.CreatedAt[1]
|
||||
}
|
||||
res, err := orderServ.Search(
|
||||
request.Id,
|
||||
request.OrderNo,
|
||||
request.MerchantId,
|
||||
request.ProductId,
|
||||
request.OutTradeNo,
|
||||
request.RechargeAccount,
|
||||
request.AccountType,
|
||||
request.Status,
|
||||
request.TransferStatus,
|
||||
start,
|
||||
end,
|
||||
request.PageSize,
|
||||
request.PageNum,
|
||||
)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
var response []*orderEnt.SearchResp = nil
|
||||
|
||||
if len(res) > 0 {
|
||||
for _, item := range res {
|
||||
response = append(response, &orderEnt.SearchResp{
|
||||
Id: item.Id,
|
||||
OrderNo: item.OrderNo,
|
||||
MerchantId: item.MerchantId,
|
||||
ProductId: item.ProductId,
|
||||
OutTradeNo: item.OutTradeNo,
|
||||
RechargeAccount: item.RechargeAccount,
|
||||
AccountType: item.AccountType,
|
||||
Number: item.Number,
|
||||
NotifyUrl: item.NotifyUrl,
|
||||
ExtendParameter: item.ExtendParameter,
|
||||
Status: item.Status,
|
||||
TransferStatus: item.TransferStatus,
|
||||
CreatedAt: item.CreatedAt.Format(time.RFC3339),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
total, err := orderServ.CountAll(
|
||||
request.Id,
|
||||
request.OrderNo,
|
||||
request.MerchantId,
|
||||
request.ProductId,
|
||||
request.OutTradeNo,
|
||||
request.RechargeAccount,
|
||||
request.AccountType,
|
||||
request.Status,
|
||||
request.TransferStatus,
|
||||
start,
|
||||
end,
|
||||
)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
common.SuccessWithList(c, response, total)
|
||||
}
|
||||
|
||||
func Create(c *gin.Context) {
|
||||
request := new(orderEnt.CreateReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
orders := &orderMod.Orders{
|
||||
OrderNo: "12321",
|
||||
MerchantId: request.MerchantId,
|
||||
ProductId: request.ProductId,
|
||||
OutTradeNo: request.OutTradeNo,
|
||||
RechargeAccount: request.RechargeAccount,
|
||||
AccountType: request.AccountType,
|
||||
Number: request.Number,
|
||||
NotifyUrl: request.NotifyUrl,
|
||||
ExtendParameter: request.ExtendParameter,
|
||||
Status: request.Status,
|
||||
TransferStatus: request.TransferStatus,
|
||||
}
|
||||
|
||||
affected, err := orderServ.Create(orders)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &orderEnt.CreateResp{
|
||||
Id: orders.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Update(c *gin.Context) {
|
||||
request := new(orderEnt.UpdateReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
orders := &orderMod.Orders{
|
||||
Id: request.Id,
|
||||
MerchantId: request.MerchantId,
|
||||
ProductId: request.ProductId,
|
||||
OutTradeNo: request.OutTradeNo,
|
||||
RechargeAccount: request.RechargeAccount,
|
||||
AccountType: request.AccountType,
|
||||
Number: request.Number,
|
||||
NotifyUrl: request.NotifyUrl,
|
||||
ExtendParameter: request.ExtendParameter,
|
||||
Status: request.Status,
|
||||
TransferStatus: request.TransferStatus,
|
||||
}
|
||||
|
||||
affected, err := orderServ.Update(orders)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &orderEnt.UpdateResp{
|
||||
Id: orders.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Delete(c *gin.Context) {
|
||||
request := new(orderEnt.DeleteReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := orderServ.Delete(request.Id)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &orderEnt.DeleteResp{
|
||||
Id: request.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
package product
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"com.snow.auto_monitor/app/constants/errorcode"
|
||||
common "com.snow.auto_monitor/app/http/controllers"
|
||||
proEnt "com.snow.auto_monitor/app/http/entities/product"
|
||||
proMod "com.snow.auto_monitor/app/models/product"
|
||||
proServ "com.snow.auto_monitor/app/services/product"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func GetById(c *gin.Context) {
|
||||
request := new(proEnt.GetListByIdReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := proServ.GetById(request.Id)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
var response *proEnt.GetListByIdResp = nil
|
||||
|
||||
if res != nil {
|
||||
|
||||
response = &proEnt.GetListByIdResp{
|
||||
Id: res.Id,
|
||||
Name: res.Name,
|
||||
Price: res.Price,
|
||||
CreatedAt: res.CreatedAt.Format(time.RFC3339),
|
||||
}
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Search(c *gin.Context) {
|
||||
request := new(proEnt.SearcgReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
start, end := "", ""
|
||||
if len(request.CreatedAt) > 1 {
|
||||
start = request.CreatedAt[0]
|
||||
end = request.CreatedAt[1]
|
||||
}
|
||||
res, err := proServ.Search(
|
||||
request.Id,
|
||||
request.Name,
|
||||
start,
|
||||
end,
|
||||
request.PageSize,
|
||||
request.PageNum,
|
||||
)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
var response []*proEnt.SearchResp = nil
|
||||
|
||||
if len(res) > 0 {
|
||||
for _, item := range res {
|
||||
response = append(response, &proEnt.SearchResp{
|
||||
Id: item.Id,
|
||||
Name: item.Name,
|
||||
Price: item.Price,
|
||||
CreatedAt: item.CreatedAt.Format(time.RFC3339),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
total, err := proServ.CountAll(
|
||||
request.Id,
|
||||
request.Name,
|
||||
start,
|
||||
end,
|
||||
)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
common.SuccessWithList(c, response, total)
|
||||
}
|
||||
|
||||
func Create(c *gin.Context) {
|
||||
request := new(proEnt.CreateReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
product := &proMod.Product{
|
||||
Name: request.Name,
|
||||
Price: request.Price,
|
||||
}
|
||||
|
||||
affected, err := proServ.Create(product)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &proEnt.CreateResp{
|
||||
Id: product.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Update(c *gin.Context) {
|
||||
request := new(proEnt.UpdateReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
product := &proMod.Product{
|
||||
Id: request.Id,
|
||||
Name: request.Name,
|
||||
Price: request.Price,
|
||||
}
|
||||
|
||||
affected, err := proServ.Update(product)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &proEnt.UpdateResp{
|
||||
Id: product.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Delete(c *gin.Context) {
|
||||
request := new(proEnt.DeleteReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := proServ.Delete(request.Id)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &proEnt.DeleteResp{
|
||||
Id: request.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"com.snow.auto_monitor/app/constants/errorcode"
|
||||
"com.snow.auto_monitor/app/http/entities"
|
||||
"com.snow.auto_monitor/app/http/formatters/bannerformatter"
|
||||
"com.snow.auto_monitor/app/services/bannerservice"
|
||||
"com.snow.auto_monitor/app/utils/httpclient"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/qit-team/snow-core/log/logger"
|
||||
)
|
||||
|
||||
// hello示例
|
||||
func HandleHello(c *gin.Context) {
|
||||
logger.Debug(c, "hello", "test message")
|
||||
client := httpclient.NewClient(c.Request.Context())
|
||||
resposne, err := client.R().Get("https://www.baidu.com")
|
||||
if err != nil {
|
||||
Error(c, errorcode.SystemError, err.Error())
|
||||
return
|
||||
}
|
||||
logger.Info(c, "HandleHello", resposne.String())
|
||||
Success(c, "hello world!")
|
||||
return
|
||||
}
|
||||
|
||||
// request和response的示例
|
||||
// HandleTest godoc
|
||||
// @Summary request和response的示例
|
||||
// @Description request和response的示例
|
||||
// @Tags snow
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param test body entities.TestRequest true "test request"
|
||||
// @Success 200 {array} entities.TestResponse
|
||||
// @Failure 400 {object} controllers.HTTPError
|
||||
// @Failure 404 {object} controllers.HTTPError
|
||||
// @Failure 500 {object} controllers.HTTPError
|
||||
// @Router /test [post]
|
||||
func HandleTest(c *gin.Context) {
|
||||
request := new(entities.TestRequest)
|
||||
err := GenRequest(c, request)
|
||||
if err != nil {
|
||||
Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
response := new(entities.TestResponse)
|
||||
response.Name = request.Name
|
||||
response.Url = request.Url
|
||||
response.Id = time.Now().Unix()
|
||||
Success(c, response)
|
||||
return
|
||||
}
|
||||
|
||||
// 测试数据库服务示例
|
||||
func GetBannerList(c *gin.Context) {
|
||||
pageStr := c.Query("page")
|
||||
limitStr := c.DefaultQuery("limit", "20")
|
||||
|
||||
page, _ := strconv.Atoi(pageStr)
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
limit, _ := strconv.Atoi(limitStr)
|
||||
if limit <= 0 {
|
||||
limit = 20
|
||||
}
|
||||
|
||||
list, err := bannerservice.GetListByPid(1, limit, page)
|
||||
if err != nil {
|
||||
Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"page": page,
|
||||
"limit": limit,
|
||||
"data": bannerformatter.FormatList(list),
|
||||
}
|
||||
|
||||
Success(c, data)
|
||||
}
|
||||
|
||||
// validator的示例
|
||||
// HandleTestValidator godoc
|
||||
// @Summary HandleTestValidator的示例
|
||||
// @Description HandleTestValidator的示例
|
||||
// @Tags snow
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param testValidator body entities.TestValidatorRequest true "example of validator"
|
||||
// @Success 200 {array} entities.TestValidatorRequest
|
||||
// @Failure 400 {object} controllers.HTTPError
|
||||
// @Failure 404 {object} controllers.HTTPError
|
||||
// @Failure 500 {object} controllers.HTTPError
|
||||
// @Router /test_validator [post]
|
||||
func HandleTestValidator(c *gin.Context) {
|
||||
request := new(entities.TestValidatorRequest)
|
||||
err := GenRequest(c, request)
|
||||
if err != nil {
|
||||
Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
Success(c, request)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package orders
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
common "com.snow.auto_monitor/app/http/controllers"
|
||||
transEnt "com.snow.auto_monitor/app/http/entities/transfersys"
|
||||
orderMod "com.snow.auto_monitor/app/models/orders"
|
||||
ransServ "com.snow.auto_monitor/app/services/transfersys"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func GetOrder(c *gin.Context) {
|
||||
item, err := ransServ.ReadGroup()
|
||||
if err != nil {
|
||||
common.Error(c, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var response *transEnt.GetOrderResp = nil
|
||||
|
||||
if item != nil {
|
||||
response = &transEnt.GetOrderResp{
|
||||
Id: item.Id,
|
||||
OrderNo: item.OrderNo,
|
||||
MerchantId: item.MerchantId,
|
||||
ProductId: item.ProductId,
|
||||
OutTradeNo: item.OutTradeNo,
|
||||
RechargeAccount: item.RechargeAccount,
|
||||
AccountType: item.AccountType,
|
||||
Number: item.Number,
|
||||
NotifyUrl: item.NotifyUrl,
|
||||
ExtendParameter: item.ExtendParameter,
|
||||
Status: item.Status,
|
||||
TransferStatus: item.TransferStatus,
|
||||
CreatedAt: item.CreatedAt.Format(time.RFC3339),
|
||||
}
|
||||
} else {
|
||||
c.JSON(500, gin.H{
|
||||
"code": 500,
|
||||
"message": "no data",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func FinishOrder(c *gin.Context) {
|
||||
request := new(transEnt.FinishOrderReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
status := 5
|
||||
if request.Result == "success" {
|
||||
status = 1
|
||||
} else if request.Result == "fail" {
|
||||
status = 4
|
||||
}
|
||||
|
||||
orders := &orderMod.Orders{
|
||||
Id: request.Id,
|
||||
ProductId: request.ProductId,
|
||||
MerchantId: request.MerchantId,
|
||||
TransferStatus: int64(status),
|
||||
}
|
||||
|
||||
affected, err := ransServ.FinishOrder(orders)
|
||||
if err != nil || affected == 0 {
|
||||
common.Error(c, 400, "无法修改已完成订单")
|
||||
return
|
||||
}
|
||||
|
||||
response := &transEnt.FinishOrderResp{
|
||||
Id: orders.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
package whitelist
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"com.snow.auto_monitor/app/constants/errorcode"
|
||||
common "com.snow.auto_monitor/app/http/controllers"
|
||||
wlCon "com.snow.auto_monitor/app/http/entities/whitelist"
|
||||
wlMod "com.snow.auto_monitor/app/models/whitelist"
|
||||
wlServ "com.snow.auto_monitor/app/services/whitelist"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func GetById(c *gin.Context) {
|
||||
request := new(wlCon.GetListByIdReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := wlServ.GetById(request.Id)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
var response *wlCon.GetListByIdResp = nil
|
||||
|
||||
if res != nil {
|
||||
|
||||
response = &wlCon.GetListByIdResp{
|
||||
Id: res.Id,
|
||||
MerchantId: res.MerchantId,
|
||||
Ip: res.Ip,
|
||||
CreatedAt: res.CreatedAt.Format(time.RFC3339),
|
||||
}
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Search(c *gin.Context) {
|
||||
request := new(wlCon.SearcgReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
start, end := "", ""
|
||||
if len(request.CreatedAt) > 1 {
|
||||
start = request.CreatedAt[0]
|
||||
end = request.CreatedAt[1]
|
||||
}
|
||||
res, err := wlServ.Search(
|
||||
request.Id,
|
||||
request.MerchantId,
|
||||
request.Ip,
|
||||
start,
|
||||
end,
|
||||
request.PageSize,
|
||||
request.PageNum,
|
||||
)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
var response []*wlCon.SearchResp = nil
|
||||
|
||||
if len(res) > 0 {
|
||||
for _, item := range res {
|
||||
response = append(response, &wlCon.SearchResp{
|
||||
Id: item.Id,
|
||||
MerchantId: item.MerchantId,
|
||||
Ip: item.Ip,
|
||||
CreatedAt: item.CreatedAt.Format(time.RFC3339),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
total, err := wlServ.CountAll(
|
||||
request.Id,
|
||||
request.MerchantId,
|
||||
request.Ip,
|
||||
start,
|
||||
end,
|
||||
)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
common.SuccessWithList(c, response, total)
|
||||
}
|
||||
|
||||
func Create(c *gin.Context) {
|
||||
request := new(wlCon.CreateReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
whitelist := &wlMod.Whitelist{
|
||||
MerchantId: request.MerchantId,
|
||||
Ip: request.Ip,
|
||||
}
|
||||
|
||||
affected, err := wlServ.Create(whitelist)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &wlCon.CreateResp{
|
||||
Id: whitelist.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Update(c *gin.Context) {
|
||||
request := new(wlCon.UpdateReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
whitelist := &wlMod.Whitelist{
|
||||
Id: request.Id,
|
||||
MerchantId: request.MerchantId,
|
||||
Ip: request.Ip,
|
||||
}
|
||||
|
||||
affected, err := wlServ.Update(whitelist)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &wlCon.UpdateResp{
|
||||
Id: whitelist.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func Delete(c *gin.Context) {
|
||||
request := new(wlCon.DeleteReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, errorcode.ParamError)
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := wlServ.Delete(request.Id)
|
||||
if err != nil && affected > 0 {
|
||||
common.Error500(c)
|
||||
return
|
||||
}
|
||||
|
||||
response := &wlCon.DeleteResp{
|
||||
Id: request.Id,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package orders
|
||||
|
||||
import (
|
||||
common "com.snow.auto_monitor/app/http/controllers"
|
||||
zhilianEnt "com.snow.auto_monitor/app/http/entities/zhiliansys"
|
||||
orderMod "com.snow.auto_monitor/app/models/orders"
|
||||
zhilianServ "com.snow.auto_monitor/app/services/zhiliansys"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func GetByOutTradeNo(c *gin.Context) {
|
||||
|
||||
request := new(zhilianEnt.GetByOutTradeNoReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
item, err := zhilianServ.GetByOutTradeNo(request.OutTradeNo, request.MerchantId)
|
||||
if err != nil {
|
||||
common.Error(c, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var response *zhilianEnt.GetByOutTradeNoResp = nil
|
||||
|
||||
if item != nil {
|
||||
response = &zhilianEnt.GetByOutTradeNoResp{
|
||||
OutTradeNo: item.OutTradeNo,
|
||||
Status: item.Status,
|
||||
}
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
||||
|
||||
func CreateOrder(c *gin.Context) {
|
||||
request := new(zhilianEnt.CreateOrderReq)
|
||||
err := common.GenRequest(c, request)
|
||||
if err != nil {
|
||||
common.Error(c, 400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
orders := &orderMod.Orders{
|
||||
OutTradeNo: request.OutTradeNo,
|
||||
ProductId: request.ProductId,
|
||||
RechargeAccount: request.RechargeAccount,
|
||||
AccountType: request.AccountType,
|
||||
Number: request.Number,
|
||||
NotifyUrl: request.NotifyUrl,
|
||||
ExtendParameter: request.ExtendParameter,
|
||||
MerchantId: request.MerchantId,
|
||||
}
|
||||
|
||||
affected, err := zhilianServ.CreateOrder(orders)
|
||||
if err != nil || affected == 0 {
|
||||
common.Error(c, 400, "创建订单失败")
|
||||
return
|
||||
}
|
||||
|
||||
response := &zhilianEnt.CreateOrderResp{
|
||||
OutTradeNo: orders.OutTradeNo,
|
||||
}
|
||||
|
||||
common.Success(c, response)
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package merchant
|
||||
|
||||
type GetListByIdReq struct {
|
||||
Id int64 `json:"id" validate:"required" example:"1"`
|
||||
}
|
||||
|
||||
type GetListByIdResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"snow"`
|
||||
CreatedAt string `json:"created_at" example:"2020-01-01 00:00:00"`
|
||||
}
|
||||
|
||||
type SearcgReq struct {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
CreatedAt []string `json:"created_at" form:"created_at"`
|
||||
PageNum int `json:"page_num" form:"page" validate:"required"`
|
||||
PageSize int `json:"page_size" form:"page_size" validate:"required"`
|
||||
}
|
||||
|
||||
type SearchResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"snow"`
|
||||
CreatedAt string `json:"created_at" example:"2020-01-01 00:00:00"`
|
||||
}
|
||||
|
||||
type CreateReq struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Key string `json:"key" validate:"required"`
|
||||
}
|
||||
|
||||
type CreateResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
}
|
||||
|
||||
type UpdateReq struct {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
type UpdateResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
}
|
||||
|
||||
type DeleteReq struct {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
|
||||
type DeleteResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package merchant
|
||||
|
||||
type GetListByIdReq struct {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
|
||||
type GetListByIdResp struct {
|
||||
Id int64 `json:"id" `
|
||||
OrderNo string `json:"order_no"`
|
||||
MerchantId int64 `json:"merchant_id"`
|
||||
ProductId int64 `json:"product_id"`
|
||||
OutTradeNo string `json:"out_trade_no"`
|
||||
RechargeAccount string `json:"recharge_account"`
|
||||
AccountType int64 `json:"account_type"`
|
||||
Number int64 `json:"number"`
|
||||
NotifyUrl string `json:"notify_url"`
|
||||
ExtendParameter string `json:"extend_parameter"`
|
||||
Status int64 `json:"status"`
|
||||
TransferStatus int64 `json:"transfer_status"`
|
||||
CreatedAt string `json:"created_at" example:"2020-01-01 00:00:00"`
|
||||
}
|
||||
|
||||
type SearchReq struct {
|
||||
Id int64 `json:"id"`
|
||||
OrderNo string `json:"order_no"`
|
||||
MerchantId int64 `json:"merchant_id"`
|
||||
ProductId int64 `json:"product_id"`
|
||||
OutTradeNo string `json:"out_trade_no"`
|
||||
RechargeAccount string `json:"recharge_account"`
|
||||
AccountType int64 `json:"account_type"`
|
||||
Status int64 `json:"status"`
|
||||
TransferStatus int64 `json:"transfer_status"`
|
||||
CreatedAt []string `json:"created_at" form:"created_at"`
|
||||
PageNum int `json:"page_num" form:"page" validate:"required"`
|
||||
PageSize int `json:"page_size" form:"page_size" validate:"required"`
|
||||
}
|
||||
|
||||
type SearchResp struct {
|
||||
Id int64 `json:"id" `
|
||||
OrderNo string `json:"order_no"`
|
||||
MerchantId int64 `json:"merchant_id"`
|
||||
ProductId int64 `json:"product_id"`
|
||||
OutTradeNo string `json:"out_trade_no"`
|
||||
RechargeAccount string `json:"recharge_account"`
|
||||
AccountType int64 `json:"account_type"`
|
||||
Number int64 `json:"number"`
|
||||
NotifyUrl string `json:"notify_url"`
|
||||
ExtendParameter string `json:"extend_parameter"`
|
||||
Status int64 `json:"status"`
|
||||
TransferStatus int64 `json:"transfer_status"`
|
||||
CreatedAt string `json:"created_at" example:"2020-01-01 00:00:00"`
|
||||
}
|
||||
|
||||
type CreateReq struct {
|
||||
MerchantId int64 `json:"merchant_id" validate:"required"`
|
||||
ProductId int64 `json:"product_id" validate:"required"`
|
||||
OutTradeNo string `json:"out_trade_no" validate:"required"`
|
||||
RechargeAccount string `json:"recharge_account" validate:"required"`
|
||||
AccountType int64 `json:"account_type" validate:"required"`
|
||||
Number int64 `json:"number" validate:"required"`
|
||||
NotifyUrl string `json:"notify_url" validate:"required"`
|
||||
ExtendParameter string `json:"extend_parameter" validate:"required"`
|
||||
Status int64 `json:"status" validate:"required"`
|
||||
TransferStatus int64 `json:"transfer_status" validate:"required"`
|
||||
}
|
||||
|
||||
type CreateResp struct {
|
||||
Id int64 `json:"id" `
|
||||
}
|
||||
|
||||
type UpdateReq struct {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
MerchantId int64 `json:"merchant_id" validate:"required"`
|
||||
ProductId int64 `json:"product_id" validate:"required"`
|
||||
OutTradeNo string `json:"out_trade_no" validate:"required"`
|
||||
RechargeAccount string `json:"recharge_account" validate:"required"`
|
||||
AccountType int64 `json:"account_type" validate:"required"`
|
||||
Number int64 `json:"number" validate:"required"`
|
||||
NotifyUrl string `json:"notify_url" validate:"required"`
|
||||
ExtendParameter string `json:"extend_parameter" validate:"required"`
|
||||
Status int64 `json:"status" validate:"required"`
|
||||
TransferStatus int64 `json:"transfer_status" validate:"required"`
|
||||
}
|
||||
|
||||
type UpdateResp struct {
|
||||
Id int64 `json:"id" `
|
||||
}
|
||||
|
||||
type DeleteReq struct {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
|
||||
type DeleteResp struct {
|
||||
Id int64 `json:"id" `
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package merchant
|
||||
|
||||
type GetListByIdReq struct {
|
||||
Id int64 `json:"id" validate:"required" example:"1"`
|
||||
}
|
||||
|
||||
type GetListByIdResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"snow"`
|
||||
Price int64 `json:"price" example:"100"`
|
||||
CreatedAt string `json:"created_at" example:"2020-01-01 00:00:00"`
|
||||
}
|
||||
|
||||
type SearcgReq struct {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
CreatedAt []string `json:"created_at" form:"created_at"`
|
||||
PageNum int `json:"page_num" form:"page" validate:"required"`
|
||||
PageSize int `json:"page_size" form:"page_size" validate:"required"`
|
||||
}
|
||||
|
||||
type SearchResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"snow"`
|
||||
Price int64 `json:"price" example:"100"`
|
||||
CreatedAt string `json:"created_at" example:"2020-01-01 00:00:00"`
|
||||
}
|
||||
|
||||
type CreateReq struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Price int64 `json:"price" validate:"required"`
|
||||
}
|
||||
|
||||
type CreateResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
}
|
||||
|
||||
type UpdateReq struct {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Price int64 `json:"price" validate:"required"`
|
||||
}
|
||||
|
||||
type UpdateResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
}
|
||||
|
||||
type DeleteReq struct {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
|
||||
type DeleteResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package entities
|
||||
|
||||
//请求数据结构
|
||||
type TestRequest struct {
|
||||
Name string `json:"name" example:"snow"`
|
||||
Url string `json:"url" example:"github.com/qit-team/snow"`
|
||||
}
|
||||
|
||||
//返回数据结构
|
||||
type TestResponse struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"snow"`
|
||||
Url string `json:"url" example:"github.com/qit-team/snow"`
|
||||
}
|
||||
|
||||
/*
|
||||
* validator.v9文档
|
||||
* 地址https://godoc.org/gopkg.in/go-playground/validator.v9
|
||||
* 列了几个大家可能会用到的,如有遗漏,请看上面文档
|
||||
*/
|
||||
|
||||
//请求数据结构
|
||||
type TestValidatorRequest struct {
|
||||
//tips,因为组件required不管是没传值或者传 0 or "" 都通过不了,但是如果用指针类型,那么0就是0,而nil无法通过校验
|
||||
Id *int64 `json:"id" validate:"required" example:"1"`
|
||||
Age int `json:"age" validate:"required,gte=0,lte=130" example:"20"`
|
||||
Name *string `json:"name" validate:"required" example:"snow"`
|
||||
Email string `json:"email" validate:"required,email" example:"snow@github.com"`
|
||||
Url string `json:"url" validate:"required" example:"github.com/qit-team/snow"`
|
||||
Mobile string `json:"mobile" validate:"required" example:"snow"`
|
||||
RangeNum int `json:"range_num" validate:"max=10,min=1" example:"3"`
|
||||
TestNum *int `json:"test_num" validate:"required,oneof=5 7 9" example:"7"`
|
||||
Content *string `json:"content" example:"snow"`
|
||||
Addresses []*Address `json:"addresses" validate:"required,dive,required" `
|
||||
}
|
||||
|
||||
// Address houses a users address information
|
||||
type Address struct {
|
||||
Street string `json:"street" validate:"required" example:"huandaodonglu"`
|
||||
City string `json:"city" validate:"required" example:"xiamen"`
|
||||
Planet string `json:"planet" validate:"required" example:"snow"`
|
||||
Phone string `json:"phone" validate:"required" example:"snow"`
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package merchant
|
||||
|
||||
type GetOrderReq struct {
|
||||
}
|
||||
|
||||
type GetOrderResp struct {
|
||||
Id int64 `json:"id" `
|
||||
OrderNo string `json:"order_no"`
|
||||
MerchantId int64 `json:"merchant_id"`
|
||||
ProductId int64 `json:"product_id"`
|
||||
OutTradeNo string `json:"out_trade_no"`
|
||||
RechargeAccount string `json:"recharge_account"`
|
||||
AccountType int64 `json:"account_type"`
|
||||
Number int64 `json:"number"`
|
||||
NotifyUrl string `json:"notify_url"`
|
||||
ExtendParameter string `json:"extend_parameter"`
|
||||
Status int64 `json:"status"`
|
||||
TransferStatus int64 `json:"transfer_status"`
|
||||
CreatedAt string `json:"created_at" example:"2020-01-01 00:00:00"`
|
||||
}
|
||||
|
||||
type FinishOrderReq struct {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
OrderNo string `json:"order_no" validate:"required"`
|
||||
ProductId int64 `json:"product_id" validate:"required"`
|
||||
MerchantId int64 `json:"merchant_id" validate:"required"`
|
||||
Result string `json:"result" validate:"required"`
|
||||
}
|
||||
|
||||
type FinishOrderResp struct {
|
||||
Id int64 `json:"id"`
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package merchant
|
||||
|
||||
type GetListByIdReq struct {
|
||||
Id int64 `json:"id" validate:"required" example:"1"`
|
||||
}
|
||||
|
||||
type GetListByIdResp struct {
|
||||
Id int64 `json:"id"`
|
||||
MerchantId int64 `json:"merchant_id"`
|
||||
Ip string `json:"ip"`
|
||||
CreatedAt string `json:"created_at" example:"2020-01-01 00:00:00"`
|
||||
}
|
||||
|
||||
type SearcgReq struct {
|
||||
Id int64 `json:"id"`
|
||||
MerchantId int64 `json:"merchant_id"`
|
||||
Ip string `json:"ip"`
|
||||
CreatedAt []string `json:"created_at" form:"created_at"`
|
||||
PageNum int `json:"page_num" form:"page" validate:"required"`
|
||||
PageSize int `json:"page_size" form:"page_size" validate:"required"`
|
||||
}
|
||||
|
||||
type SearchResp struct {
|
||||
Id int64 `json:"id"`
|
||||
MerchantId int64 `json:"merchant_id"`
|
||||
Ip string `json:"ip"`
|
||||
CreatedAt string `json:"created_at" example:"2020-01-01 00:00:00"`
|
||||
}
|
||||
|
||||
type CreateReq struct {
|
||||
MerchantId int64 `json:"merchant_id" validate:"required"`
|
||||
Ip string `json:"ip" validate:"required"`
|
||||
}
|
||||
|
||||
type CreateResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
}
|
||||
|
||||
type UpdateReq struct {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
MerchantId int64 `json:"merchant_id" validate:"required"`
|
||||
Ip string `json:"ip" validate:"required"`
|
||||
}
|
||||
|
||||
type UpdateResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
}
|
||||
|
||||
type DeleteReq struct {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
|
||||
type DeleteResp struct {
|
||||
Id int64 `json:"id" example:"1"`
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package merchant
|
||||
|
||||
type GetByOutTradeNoReq struct {
|
||||
OutTradeNo string `json:"out_trade_no" validate:"required"`
|
||||
MerchantId int64 `json:"merchant_id" validate:"required"`
|
||||
TimeStamp int64 `json:"time_stamp" validate:"required"`
|
||||
Sign string `json:"sign" validate:"required"`
|
||||
}
|
||||
|
||||
type GetByOutTradeNoResp struct {
|
||||
Status int64 `json:"status"`
|
||||
OutTradeNo string `json:"out_trade_no"`
|
||||
}
|
||||
|
||||
type CreateOrderReq struct {
|
||||
OutTradeNo string `json:"out_trade_no" validate:"required"`
|
||||
ProductId int64 `json:"product_id" validate:"required"`
|
||||
RechargeAccount string `json:"recharge_account" validate:"required"`
|
||||
AccountType int64 `json:"account_type" validate:"required"`
|
||||
Number int64 `json:"number" validate:"required"`
|
||||
NotifyUrl string `json:"notify_url" validate:"required"`
|
||||
ExtendParameter string `json:"extend_parameter" validate:"required"`
|
||||
|
||||
MerchantId int64 `json:"merchant_id" validate:"required"`
|
||||
TimeStamp int64 `json:"time_stamp" validate:"required"`
|
||||
Sign string `json:"sign" validate:"required"`
|
||||
}
|
||||
|
||||
type CreateOrderResp struct {
|
||||
OutTradeNo string `json:"out_trade_no"`
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package bannerformatter
|
||||
|
||||
import (
|
||||
"com.snow.auto_monitor/app/models/bannermodel"
|
||||
)
|
||||
|
||||
type BannerFormatter struct {
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Img string `json:"image"`
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
func FormatList(bannerList []*bannermodel.Banner) (res []*BannerFormatter) {
|
||||
res = make([]*BannerFormatter, len(bannerList))
|
||||
|
||||
for k, banner := range bannerList {
|
||||
one := FormatOne(banner)
|
||||
res[k] = one
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
//单条消息的格式化,
|
||||
func FormatOne(banner *bannermodel.Banner) (res *BannerFormatter) {
|
||||
res = &BannerFormatter{
|
||||
Id: int(banner.Id),
|
||||
Title: banner.Title,
|
||||
Img: banner.ImageUrl,
|
||||
Url: banner.Url,
|
||||
}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package bannerformatter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"com.snow.auto_monitor/app/models/bannermodel"
|
||||
)
|
||||
|
||||
func TesFormatOne(t *testing.T) {
|
||||
a := &bannermodel.Banner{
|
||||
Id: 1,
|
||||
Title: "test",
|
||||
ImageUrl: "http://x/1.jpg",
|
||||
Url: "http://x",
|
||||
Status: "1",
|
||||
}
|
||||
b := FormatOne(a)
|
||||
if b.Title != a.Title || b.Img != a.ImageUrl || b.Url != a.Url {
|
||||
t.Error("FormatOne not same")
|
||||
}
|
||||
}
|
||||
|
||||
func TesFormatList(t *testing.T) {
|
||||
a := make([]*bannermodel.Banner, 2)
|
||||
a[0] = &bannermodel.Banner{
|
||||
Id: 1,
|
||||
Title: "test",
|
||||
ImageUrl: "http://x1/1.jpg",
|
||||
Url: "http://x1",
|
||||
Status: "1",
|
||||
}
|
||||
a[1] = &bannermodel.Banner{
|
||||
Id: 2,
|
||||
Title: "test2",
|
||||
ImageUrl: "http://x/2.jpg",
|
||||
Url: "http://x2",
|
||||
Status: "2",
|
||||
}
|
||||
b := FormatList(a)
|
||||
for k, v := range b {
|
||||
if v.Title != a[k].Title || v.Img != a[k].ImageUrl || v.Url != a[k].Url {
|
||||
t.Error("FormatList not same")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package metric
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"com.snow.auto_monitor/app/utils/metric"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const (
|
||||
HOST = "host"
|
||||
PATH = "path" // 路径
|
||||
METHOD = "method" // 方法
|
||||
CODE = "code" // 错误码
|
||||
|
||||
// metric
|
||||
ALL_REQ_TOTAL_COUNT = "all_req_total_count" // 所有URL总请求数
|
||||
ALL_REQ_COST_TIME = "all_req_cost_time" // 所有URL请求耗时
|
||||
|
||||
REQ_TOTAL_COUNT = "req_total_count" // 每个URL总请求数
|
||||
REQ_COST_TIME = "req_cost_time" // 每个URL请求耗时
|
||||
)
|
||||
|
||||
func init() {
|
||||
metric.RegisterCollector(reqTotalCounter, reqCostTimeObserver, allReqTotalCounter, allReqCostTimeObserver)
|
||||
}
|
||||
|
||||
var (
|
||||
reqTotalCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: REQ_TOTAL_COUNT,
|
||||
}, []string{PATH, METHOD})
|
||||
|
||||
reqCostTimeObserver = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: REQ_COST_TIME,
|
||||
Buckets: []float64{
|
||||
100,
|
||||
200,
|
||||
500,
|
||||
1000,
|
||||
3000,
|
||||
5000,
|
||||
},
|
||||
}, []string{PATH, METHOD})
|
||||
|
||||
allReqTotalCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: ALL_REQ_TOTAL_COUNT,
|
||||
}, []string{HOST})
|
||||
|
||||
allReqCostTimeObserver = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: ALL_REQ_COST_TIME,
|
||||
Buckets: []float64{
|
||||
100,
|
||||
200,
|
||||
500,
|
||||
1000,
|
||||
3000,
|
||||
5000,
|
||||
},
|
||||
}, []string{HOST})
|
||||
)
|
||||
|
||||
func AddReqCount(req *http.Request) {
|
||||
reqTotalCounter.WithLabelValues(req.URL.Path, req.Method).Inc()
|
||||
}
|
||||
|
||||
func CollectReqCostTime(req *http.Request, ms int64) {
|
||||
reqCostTimeObserver.WithLabelValues(req.URL.Path, req.Method).Observe(float64(ms))
|
||||
}
|
||||
|
||||
func AddAllReqCount(req *http.Request) {
|
||||
allReqTotalCounter.WithLabelValues(req.Host).Inc()
|
||||
}
|
||||
|
||||
func CollectAllReqCostTime(req *http.Request, ms int64) {
|
||||
allReqCostTimeObserver.WithLabelValues(req.Host).Observe(float64(ms))
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package middlewares
|
||||
|
||||
import (
|
||||
common "com.snow.auto_monitor/app/http/controllers"
|
||||
wlmod "com.snow.auto_monitor/app/models/whitelist"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func VerifyIp() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// 读取请求体
|
||||
reqIp := c.ClientIP()
|
||||
//验证商户是否存在
|
||||
_, has, err := wlmod.GetInstance().GetByIp(reqIp)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
if !has {
|
||||
common.Error(c, 400, "ip无权限访问")
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package middlewares
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"com.snow.auto_monitor/app/http/metric"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func CollectMetric() gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
start := time.Now()
|
||||
ctx.Next()
|
||||
dur := time.Now().Sub(start).Milliseconds()
|
||||
|
||||
metric.AddAllReqCount(ctx.Request)
|
||||
metric.CollectAllReqCostTime(ctx.Request, dur)
|
||||
metric.AddReqCount(ctx.Request)
|
||||
metric.CollectReqCostTime(ctx.Request, dur)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package middlewares
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/qit-team/snow-core/log/logger"
|
||||
)
|
||||
|
||||
func RequestLog() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
bodyBytes, err := ioutil.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
logger.Info(c, "LogRequset", "Failed to read request body:"+err.Error())
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
// 将请求体重置,以便后续处理可以再次读取
|
||||
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
|
||||
|
||||
infstr := "Date: " + time.Now().Format("2006-01-02 15:04:05") + " "
|
||||
// 构建日志信息
|
||||
infstr += "Request: " + c.Request.Method + " " + c.Request.URL.Path + " "
|
||||
infstr += "From: " + c.ClientIP() + " "
|
||||
infstr += "Body: " + string(bodyBytes)
|
||||
logger.Info(c, "LogRequset", infstr)
|
||||
|
||||
// 调用下一个中间件
|
||||
c.Next()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package middlewares
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
syslog "log"
|
||||
"net/http/httputil"
|
||||
"runtime/debug"
|
||||
|
||||
"com.snow.auto_monitor/app/constants/logtype"
|
||||
"com.snow.auto_monitor/config"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/qit-team/snow-core/log/logger"
|
||||
)
|
||||
|
||||
func ServerRecovery() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
httpRequest, _ := httputil.DumpRequest(c.Request, false)
|
||||
msg := map[string]interface{}{
|
||||
"error": err,
|
||||
"request": string(httpRequest),
|
||||
"stack": string(debug.Stack()),
|
||||
}
|
||||
msgJson, _ := json.Marshal(msg)
|
||||
logger.GetLogger().Error(string(msgJson), logtype.GoPanic, c)
|
||||
|
||||
if config.IsDebug() {
|
||||
//本地开发 debug 模式开启时输出错误信息到shell
|
||||
syslog.Println(err)
|
||||
}
|
||||
|
||||
c.JSON(500, gin.H{
|
||||
"code": 500,
|
||||
"msg": "system error",
|
||||
"request_uri": c.Request.URL.Path,
|
||||
"data": make(map[string]string),
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
//before request
|
||||
|
||||
c.Next()
|
||||
|
||||
//after request
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package middlewares
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
common "com.snow.auto_monitor/app/http/controllers"
|
||||
mermod "com.snow.auto_monitor/app/models/merchant"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/qit-team/snow-core/log/logger"
|
||||
)
|
||||
|
||||
type Verify struct {
|
||||
MerchantId int64 `json:"merchant_id" validate:"required"`
|
||||
TimeStamp int64 `json:"time_stamp" validate:"required"`
|
||||
Sign string `json:"sign" validate:"required"`
|
||||
}
|
||||
|
||||
func getMD5Hash(input string) string {
|
||||
hash := md5.Sum([]byte(input))
|
||||
return hex.EncodeToString(hash[:])
|
||||
}
|
||||
|
||||
func GenMD5Sign(data map[string]interface{}, secretKey string) string {
|
||||
keys := make([]string, 0, len(data))
|
||||
for key := range data {
|
||||
if key != "sign" && key != "Sign" {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
rawStr := ""
|
||||
for _, key := range keys {
|
||||
value := fmt.Sprintf("%v", data[key])
|
||||
if rawStr != "" {
|
||||
rawStr += "&"
|
||||
}
|
||||
rawStr += fmt.Sprintf("%s=%s", key, value)
|
||||
}
|
||||
rawStr += "&key=" + secretKey
|
||||
sign := strings.ToUpper(getMD5Hash(rawStr))
|
||||
return sign
|
||||
}
|
||||
|
||||
func VerifySign() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
var data map[string]interface{}
|
||||
body, err := common.ReadBody(c)
|
||||
if err != nil {
|
||||
common.Error(c, 400, err.Error())
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
common.Error(c, 400, err.Error())
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
if data["merchant_id"] == nil || data["time_stamp"] == nil || data["sign"] == nil {
|
||||
common.Error(c, 400, "参数错误")
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
//验证商户是否存在
|
||||
merchanId := int64(data["merchant_id"].(float64))
|
||||
merchant, has, err := mermod.GetInstance().GetById(merchanId)
|
||||
if err != nil {
|
||||
common.Error500(c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
if !has {
|
||||
common.Error(c, 400, "商户不存在")
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
//验证签名是否正确
|
||||
hash := GenMD5Sign(data, merchant.Key)
|
||||
logger.Info(c, "Sign", hash)
|
||||
if hash != data["sign"] {
|
||||
common.Error(c, 400, "签名错误")
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package middlewares
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"com.snow.auto_monitor/app/http/trace"
|
||||
|
||||
"github.com/SkyAPM/go2sky"
|
||||
"github.com/SkyAPM/go2sky/propagation"
|
||||
v3 "github.com/SkyAPM/go2sky/reporter/grpc/language-agent"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/qit-team/snow-core/log/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
componentIDGOHttpServer = 5004
|
||||
)
|
||||
|
||||
func Trace() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
tracer, err := trace.Tracer()
|
||||
if err != nil {
|
||||
logger.Error(c, "Trace", err.Error())
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
r := c.Request
|
||||
operationName := fmt.Sprintf("/%s%s", r.Method, r.URL.Path)
|
||||
span, ctx, err := tracer.CreateEntrySpan(c, operationName, func() (string, error) {
|
||||
// 从http头部捞取上一层的调用链信息, 当前使用v3版本的协议
|
||||
// https://github.com/apache/skywalking/blob/master/docs/en/protocols/Skywalking-Cross-Process-Propagation-Headers-Protocol-v3.md
|
||||
return r.Header.Get(propagation.Header), nil
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error(c, "Trace", err.Error())
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
span.SetComponent(componentIDGOHttpServer)
|
||||
// 可以自定义tag
|
||||
span.Tag(go2sky.TagHTTPMethod, r.Method)
|
||||
span.Tag(go2sky.TagURL, fmt.Sprintf("%s%s", r.Host, r.URL.Path))
|
||||
span.SetSpanLayer(v3.SpanLayer_Http)
|
||||
c.Request = c.Request.WithContext(ctx)
|
||||
c.Next()
|
||||
code := c.Writer.Status()
|
||||
if code >= 400 {
|
||||
span.Error(time.Now(), fmt.Sprintf("Error on handling request, statusCode: %d", code))
|
||||
}
|
||||
span.Tag(go2sky.TagStatusCode, strconv.Itoa(code))
|
||||
span.End()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package routes
|
||||
|
||||
/**
|
||||
* 配置路由
|
||||
*/
|
||||
import (
|
||||
"com.snow.auto_monitor/app/http/controllers"
|
||||
"com.snow.auto_monitor/app/http/middlewares"
|
||||
"com.snow.auto_monitor/app/http/trace"
|
||||
"com.snow.auto_monitor/app/utils/metric"
|
||||
"com.snow.auto_monitor/config"
|
||||
|
||||
merCon "com.snow.auto_monitor/app/http/controllers/merchant"
|
||||
ordersCon "com.snow.auto_monitor/app/http/controllers/orders"
|
||||
proCon "com.snow.auto_monitor/app/http/controllers/product"
|
||||
transCon "com.snow.auto_monitor/app/http/controllers/transfersys"
|
||||
wlCon "com.snow.auto_monitor/app/http/controllers/whitelist"
|
||||
zlCon "com.snow.auto_monitor/app/http/controllers/zhiliansys"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/qit-team/snow-core/http/middleware"
|
||||
"github.com/qit-team/snow-core/log/logger"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
"github.com/swaggo/gin-swagger/swaggerFiles"
|
||||
)
|
||||
|
||||
// api路由配置
|
||||
func RegisterRoute(router *gin.Engine) {
|
||||
//middleware: 服务错误处理 => 生成请求id => access log
|
||||
router.Use(middlewares.ServerRecovery(), middleware.GenRequestId, middleware.GenContextKit, middleware.AccessLog(), middlewares.VerifyIp())
|
||||
|
||||
if config.GetConf().PrometheusCollectEnable && config.IsEnvEqual(config.ProdEnv) {
|
||||
router.Use(middlewares.CollectMetric())
|
||||
metric.Init(metric.EnableRuntime(), metric.EnableProcess())
|
||||
metricHandler := metric.Handler()
|
||||
router.GET("/metrics", func(ctx *gin.Context) {
|
||||
metricHandler.ServeHTTP(ctx.Writer, ctx.Request)
|
||||
})
|
||||
}
|
||||
|
||||
if len(config.GetConf().SkyWalkingOapServer) > 0 && config.IsEnvEqual(config.ProdEnv) {
|
||||
err := trace.InitTracer(config.GetConf().ServiceName, config.GetConf().SkyWalkingOapServer)
|
||||
if err != nil {
|
||||
logger.Error(nil, "InitTracer", err.Error())
|
||||
} else {
|
||||
router.Use(middlewares.Trace())
|
||||
}
|
||||
}
|
||||
|
||||
router.NoRoute(controllers.Error404)
|
||||
router.GET("/hello", controllers.HandleHello)
|
||||
router.POST("/test", controllers.HandleTest)
|
||||
router.POST("/test_validator", controllers.HandleTestValidator)
|
||||
|
||||
//api版本
|
||||
v1 := router.Group("/v1")
|
||||
{
|
||||
v1.GET("/banner_list", controllers.GetBannerList)
|
||||
}
|
||||
|
||||
merchant := router.Group("/merchant")
|
||||
{
|
||||
merchant.POST("/get_by_id", merCon.GetById)
|
||||
merchant.POST("/search", merCon.Search)
|
||||
merchant.POST("/create", merCon.Create)
|
||||
// merchant.POST("/update", merCon.Update)
|
||||
// merchant.POST("/delete", merCon.Delete)
|
||||
}
|
||||
|
||||
orders := router.Group("/orders")
|
||||
{
|
||||
orders.POST("/get_by_id", ordersCon.GetById)
|
||||
orders.POST("/search", ordersCon.Search)
|
||||
// orders.POST("/create", ordersCon.Create)
|
||||
// orders.POST("/update", ordersCon.Update)
|
||||
// orders.POST("/delete", ordersCon.Delete)
|
||||
}
|
||||
|
||||
product := router.Group("/product")
|
||||
{
|
||||
product.POST("/get_by_id", proCon.GetById)
|
||||
product.POST("/search", proCon.Search)
|
||||
product.POST("/create", proCon.Create)
|
||||
// product.POST("/update", proCon.Update)
|
||||
// product.POST("/delete", proCon.Delete)
|
||||
}
|
||||
|
||||
whitelist := router.Group("/whitelist")
|
||||
{
|
||||
whitelist.POST("/get_by_id", wlCon.GetById)
|
||||
whitelist.POST("/search", wlCon.Search)
|
||||
whitelist.POST("/create", wlCon.Create)
|
||||
// whitelist.POST("/update", wlCon.Update)
|
||||
// whitelist.POST("/delete", wlCon.Delete)
|
||||
}
|
||||
|
||||
zhilian := router.Group("/zhilian")
|
||||
// zhilian.Use(middlewares.VerifySign())
|
||||
zhilian.Use(middlewares.RequestLog())
|
||||
{
|
||||
zhilian.POST("/recharge/order", zlCon.CreateOrder)
|
||||
zhilian.POST("/recharge/query", zlCon.GetByOutTradeNo)
|
||||
}
|
||||
|
||||
transfersys := router.Group("/transfersys")
|
||||
transfersys.Use(middlewares.RequestLog())
|
||||
{
|
||||
transfersys.GET("/recharge/get_order", transCon.GetOrder)
|
||||
transfersys.POST("/recharge/finish", transCon.FinishOrder)
|
||||
}
|
||||
|
||||
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package trace
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"com.snow.auto_monitor/config"
|
||||
|
||||
"github.com/SkyAPM/go2sky"
|
||||
"github.com/SkyAPM/go2sky/reporter"
|
||||
)
|
||||
|
||||
var (
|
||||
tracer *go2sky.Tracer
|
||||
lock sync.Mutex
|
||||
)
|
||||
|
||||
func Tracer() (*go2sky.Tracer, error) {
|
||||
if tracer == nil {
|
||||
// 有err, 不适合用sync.Once做单例
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
if tracer == nil {
|
||||
err := InitTracer(config.GetConf().ServiceName, config.GetConf().SkyWalkingOapServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return tracer, nil
|
||||
}
|
||||
|
||||
func InitTracer(serviceName, skyWalkingOapServer string) error {
|
||||
report, err := reporter.NewGRPCReporter(skyWalkingOapServer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tracer, err = go2sky.NewTracer(serviceName, go2sky.WithReporter(report))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package basejob
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/qit-team/work"
|
||||
)
|
||||
|
||||
var (
|
||||
jb *work.Job
|
||||
register func(job *work.Job)
|
||||
mu sync.RWMutex
|
||||
)
|
||||
|
||||
func SetJob(job *work.Job) {
|
||||
if jb == nil {
|
||||
jb = job
|
||||
}
|
||||
}
|
||||
|
||||
func SetJobRegister(r func(*work.Job)) {
|
||||
register = r
|
||||
}
|
||||
|
||||
func GetJob() *work.Job {
|
||||
if jb == nil {
|
||||
if register != nil {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
jb = work.New()
|
||||
register(jb)
|
||||
} else {
|
||||
panic("job register is nil")
|
||||
}
|
||||
}
|
||||
return jb
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息入队 -- 原始message
|
||||
*/
|
||||
func Enqueue(ctx context.Context, topic string, message string, args ...interface{}) (isOk bool, err error) {
|
||||
return GetJob().Enqueue(ctx, topic, message, args...)
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息入队 -- Task数据结构
|
||||
*/
|
||||
func EnqueueWithTask(ctx context.Context, topic string, task work.Task, args ...interface{}) (isOk bool, err error) {
|
||||
return GetJob().EnqueueWithTask(ctx, topic, task, args...)
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息批量入队 -- 原始message
|
||||
*/
|
||||
func BatchEnqueue(ctx context.Context, topic string, messages []string, args ...interface{}) (isOk bool, err error) {
|
||||
return GetJob().BatchEnqueue(ctx, topic, messages, args...)
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息批量入队 -- Task数据结构
|
||||
*/
|
||||
func BatchEnqueueWithTask(ctx context.Context, topic string, tasks []work.Task, args ...interface{}) (isOk bool, err error) {
|
||||
return GetJob().BatchEnqueueWithTask(ctx, topic, tasks, args...)
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package jobs
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"com.snow.auto_monitor/app/jobs/basejob"
|
||||
"com.snow.auto_monitor/config"
|
||||
|
||||
"github.com/qit-team/snow-core/log/logger"
|
||||
"github.com/qit-team/snow-core/queue"
|
||||
"github.com/qit-team/snow-core/redis"
|
||||
"github.com/qit-team/work"
|
||||
)
|
||||
|
||||
/**
|
||||
* 配置队列任务
|
||||
*/
|
||||
func RegisterWorker(job *work.Job) {
|
||||
basejob.SetJob(job)
|
||||
|
||||
//设置worker的任务投递回调函数
|
||||
job.AddFunc("topic-test", test)
|
||||
//设置worker的任务投递回调函数,和并发数
|
||||
job.AddFunc("topic-test1", test, 2)
|
||||
//使用worker结构进行注册
|
||||
job.AddWorker("topic-test2", &work.Worker{Call: work.MyWorkerFunc(test), MaxConcurrency: 1})
|
||||
|
||||
RegisterQueueDriver(job)
|
||||
SetOptions(job)
|
||||
}
|
||||
|
||||
/**
|
||||
* 给topic注册对应的队列服务
|
||||
*/
|
||||
func RegisterQueueDriver(job *work.Job) {
|
||||
//设置队列服务,需要实现work.Queue接口的方法
|
||||
q := queue.GetQueue(redis.SingletonMain, queue.DriverTypeRedis)
|
||||
//针对topic设置相关的queue
|
||||
job.AddQueue(q, "topic-test1", "topic-test2")
|
||||
//设置默认的queue, 没有设置过的topic会使用默认的queue
|
||||
job.AddQueue(q)
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置配置参数
|
||||
*/
|
||||
func SetOptions(job *work.Job) {
|
||||
//设置logger,需要实现work.Logger接口的方法
|
||||
job.SetLogger(logger.GetLogger())
|
||||
|
||||
//设置启用的topic,未设置表示启用全部注册过topic
|
||||
if config.GetOptions().Queue != "" {
|
||||
topics := strings.Split(config.GetOptions().Queue, ",")
|
||||
job.SetEnableTopics(topics...)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package jobs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/qit-team/work"
|
||||
)
|
||||
|
||||
func test(task work.Task) (work.TaskResult) {
|
||||
time.Sleep(time.Millisecond * 5)
|
||||
s, err := work.JsonEncode(task)
|
||||
if err != nil {
|
||||
//work.StateFailed 不会进行ack确认
|
||||
//work.StateFailedWithAck 会进行actk确认
|
||||
//return work.TaskResult{Id: task.Id, State: work.StateFailed}
|
||||
return work.TaskResult{Id: task.Id, State: work.StateFailedWithAck}
|
||||
} else {
|
||||
//work.StateSucceed 会进行ack确认
|
||||
fmt.Println("do task", s)
|
||||
return work.TaskResult{Id: task.Id, State: work.StateSucceed}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package bannermodel
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/qit-team/snow-core/db"
|
||||
)
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
m *bannerModel
|
||||
)
|
||||
/**
|
||||
* Banner实体
|
||||
*/
|
||||
type Banner struct {
|
||||
Id int64 `xorm:"pk autoincr"` //注:使用getOne 或者ID() 需要设置主键
|
||||
Pid int
|
||||
Title string
|
||||
ImageUrl string `xorm:"'img_url'"`
|
||||
Url string
|
||||
Status string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt time.Time `xorm:"deleted"` //此特性会激发软删除
|
||||
}
|
||||
|
||||
/**
|
||||
* 表名规则
|
||||
* @wiki http://gobook.io/read/github.com/go-xorm/manual-zh-CN/chapter-02/3.tags.html
|
||||
*/
|
||||
func (m *Banner) TableName() string {
|
||||
return "banner"
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有化,防止被外部new
|
||||
*/
|
||||
type bannerModel struct {
|
||||
db.Model //组合基础Model,集成基础Model的属性和方法
|
||||
}
|
||||
|
||||
//单例模式
|
||||
func GetInstance() *bannerModel {
|
||||
once.Do(func() {
|
||||
m = new(bannerModel)
|
||||
//m.DiName = "" //设置数据库实例连接,默认db.SingletonMain
|
||||
})
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *bannerModel) GetListByPid(pid int, limits ...int) (banners []*Banner, err error) {
|
||||
banners = make([]*Banner, 0)
|
||||
err = m.GetList(&banners, "pid = ?", []interface{}{pid}, limits)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package bannermodel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/qit-team/snow-core/config"
|
||||
"github.com/qit-team/snow-core/db"
|
||||
"github.com/qit-team/snow-core/utils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m := config.DbBaseConfig{
|
||||
Host: "127.0.0.1",
|
||||
Port: 3306,
|
||||
User: "root",
|
||||
Password: "123456",
|
||||
DBName: "test",
|
||||
}
|
||||
dbConf := config.DbConfig{
|
||||
Driver: "mysql",
|
||||
Master: m,
|
||||
}
|
||||
|
||||
err := db.Pr.Register("db", dbConf, true)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOne(t *testing.T) {
|
||||
bannerModel := GetInstance()
|
||||
banner := new(Banner)
|
||||
res, err := bannerModel.GetOne(1, banner)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if res != true {
|
||||
t.Error("missing banner data")
|
||||
} else if banner.Id == 0 {
|
||||
t.Error("missing banner data")
|
||||
}
|
||||
fmt.Println(utils.JsonEncode(banner))
|
||||
}
|
||||
|
||||
func TestGetList(t *testing.T) {
|
||||
bannerModel := GetInstance()
|
||||
banners := make([]*Banner, 0)
|
||||
err := bannerModel.GetList(&banners, "pid >= ?", []interface{}{1}, []int{10}, "status desc, id desc")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
fmt.Println(utils.JsonEncode(banners))
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package merchant
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/qit-team/snow-core/db"
|
||||
)
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
m *merchantModel
|
||||
)
|
||||
|
||||
/**
|
||||
* Merchant
|
||||
*/
|
||||
type Merchant struct {
|
||||
Id int64 `xorm:"pk autoincr"` //注:使用getOne 或者ID() 需要设置主键
|
||||
Name string
|
||||
Key string
|
||||
CreatedAt time.Time `xorm:"created"`
|
||||
}
|
||||
|
||||
/**
|
||||
* 表名规则
|
||||
* @wiki http://gobook.io/read/github.com/go-xorm/manual-zh-CN/chapter-02/3.tags.html
|
||||
*/
|
||||
func (m *Merchant) TableName() string {
|
||||
return "merchant"
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有化,防止被外部new
|
||||
*/
|
||||
type merchantModel struct {
|
||||
db.Model //组合基础Model,集成基础Model的属性和方法
|
||||
}
|
||||
|
||||
// 单例模式
|
||||
func GetInstance() *merchantModel {
|
||||
once.Do(func() {
|
||||
m = new(merchantModel)
|
||||
//m.DiName = "" //设置数据库实例连接,默认db.SingletonMain
|
||||
})
|
||||
return m
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询主键ID的记录
|
||||
* @param id 主键ID
|
||||
* @return has 是否有记录
|
||||
* @return err 错误信息
|
||||
* @return merchant 查询结果
|
||||
*/
|
||||
func (m *merchantModel) GetById(id int64) (merchant *Merchant, has bool, err error) {
|
||||
merchant = &Merchant{}
|
||||
has, err = m.GetDb().ID(id).Get(merchant)
|
||||
if err == nil || !has {
|
||||
merchant = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *merchantModel) Search(id int64, name string, startTime string, endTime string, limit int, page int) (merchant []*Merchant, err error) {
|
||||
merchant = make([]*Merchant, 0)
|
||||
sql := "1=1"
|
||||
var args []interface{}
|
||||
if id != 0 {
|
||||
sql += " and id = ?"
|
||||
args = append(args, id)
|
||||
}
|
||||
if name != "" {
|
||||
sql += " and name = ?"
|
||||
args = append(args, name)
|
||||
}
|
||||
if startTime != "" && endTime != "" {
|
||||
sql += " and created_at >= ? and created_at <= ?"
|
||||
args = append(args, startTime, endTime)
|
||||
}
|
||||
err = m.GetDb().Where(sql, args...).Limit(limit, page).Find(&merchant)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *merchantModel) CountAll(id int64, name string, startTime string, endTime string) (res int64, err error) {
|
||||
sql := "1=1"
|
||||
var args []interface{}
|
||||
if id != 0 {
|
||||
sql += " and id = ?"
|
||||
args = append(args, id)
|
||||
}
|
||||
if name != "" {
|
||||
sql += " and name = ?"
|
||||
args = append(args, name)
|
||||
}
|
||||
if startTime != "" && endTime != "" {
|
||||
sql += " and created_at >= ? and created_at <= ?"
|
||||
args = append(args, startTime, endTime)
|
||||
}
|
||||
res, err = m.GetDb().Table("merchant").Where(sql, args...).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (m *merchantModel) Create(merchant *Merchant) (affected int64, err error) {
|
||||
affected, err = m.GetDb().Insert(merchant)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *merchantModel) Update(merchant *Merchant) (affected int64, err error) {
|
||||
affected, err = m.GetDb().ID(merchant.Id).Update(merchant)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *merchantModel) Delete(id int64) (affected int64, err error) {
|
||||
affected, err = m.GetDb().ID(id).Delete(&Merchant{})
|
||||
return
|
||||
}
|
|
@ -0,0 +1,277 @@
|
|||
package orders
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/qit-team/snow-core/db"
|
||||
)
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
m *ordersModel
|
||||
)
|
||||
|
||||
/**
|
||||
* Orders
|
||||
*/
|
||||
type Orders struct {
|
||||
Id int64 `xorm:"pk autoincr"` //注:使用getOne 或者ID() 需要设置主键
|
||||
OrderNo string
|
||||
MerchantId int64
|
||||
ProductId int64
|
||||
|
||||
OutTradeNo string
|
||||
RechargeAccount string
|
||||
AccountType int64
|
||||
Number int64
|
||||
NotifyUrl string
|
||||
ExtendParameter string
|
||||
|
||||
Status int64
|
||||
TransferStatus int64
|
||||
CreatedAt time.Time `xorm:"created"`
|
||||
}
|
||||
|
||||
func (o *Orders) MarshalBinary() ([]byte, error) {
|
||||
return json.Marshal(o)
|
||||
}
|
||||
|
||||
/**
|
||||
* 表名规则
|
||||
* @wiki http://gobook.io/read/github.com/go-xorm/manual-zh-CN/chapter-02/3.tags.html
|
||||
*/
|
||||
func (m *Orders) TableName() string {
|
||||
return "orders"
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有化,防止被外部new
|
||||
*/
|
||||
type ordersModel struct {
|
||||
db.Model //组合基础Model,集成基础Model的属性和方法
|
||||
}
|
||||
|
||||
// 单例模式
|
||||
func GetInstance() *ordersModel {
|
||||
once.Do(func() {
|
||||
m = new(ordersModel)
|
||||
//m.DiName = "" //设置数据库实例连接,默认db.SingletonMain
|
||||
})
|
||||
return m
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询主键ID的记录
|
||||
* @param id 主键ID
|
||||
* @return has 是否有记录
|
||||
* @return err 错误信息
|
||||
* @return orders 查询结果
|
||||
*/
|
||||
func (m *ordersModel) GetById(id int64) (orders *Orders, has bool, err error) {
|
||||
orders = &Orders{}
|
||||
has, err = m.GetDb().ID(id).Get(orders)
|
||||
if err == nil || !has {
|
||||
orders = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *ordersModel) GetByOutTradeNo(out_trade_no string, merchant_id int64) (orders *Orders, has bool, err error) {
|
||||
orders = &Orders{}
|
||||
has, err = m.GetDb().Where("out_trade_no = ? and merchant_id = ?", out_trade_no, merchant_id).Get(orders)
|
||||
if err == nil || !has {
|
||||
orders = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *ordersModel) Search(
|
||||
id int64,
|
||||
order_no string,
|
||||
merchant_id int64,
|
||||
product_id int64,
|
||||
out_trade_no string,
|
||||
recharge_account string,
|
||||
account_type int64,
|
||||
|
||||
status int64,
|
||||
transfer_status int64,
|
||||
startTime string,
|
||||
endTime string,
|
||||
limit int,
|
||||
page int) (orders []*Orders, err error) {
|
||||
orders = make([]*Orders, 0)
|
||||
sql := "1=1"
|
||||
var args []interface{}
|
||||
if id != 0 {
|
||||
sql += " and id = ?"
|
||||
args = append(args, id)
|
||||
}
|
||||
if order_no != "" {
|
||||
sql += " and order_no = ?"
|
||||
args = append(args, order_no)
|
||||
}
|
||||
if merchant_id != 0 {
|
||||
sql += " and merchant_id = ?"
|
||||
args = append(args, merchant_id)
|
||||
}
|
||||
if product_id != 0 {
|
||||
sql += " and merchant_id = ?"
|
||||
args = append(args, product_id)
|
||||
}
|
||||
if out_trade_no != "" {
|
||||
sql += " and out_trade_no = ?"
|
||||
args = append(args, out_trade_no)
|
||||
}
|
||||
if recharge_account != "" {
|
||||
sql += " and recharge_account = ?"
|
||||
args = append(args, recharge_account)
|
||||
}
|
||||
if account_type != 0 {
|
||||
sql += " and account_type = ?"
|
||||
args = append(args, recharge_account)
|
||||
}
|
||||
if status != 0 {
|
||||
sql += " and status = ?"
|
||||
args = append(args, status)
|
||||
}
|
||||
if transfer_status != 0 {
|
||||
sql += " and transfer_status = ?"
|
||||
args = append(args, transfer_status)
|
||||
}
|
||||
if startTime != "" && endTime != "" {
|
||||
sql += " and created_at >= ? and created_at <= ?"
|
||||
args = append(args, startTime, endTime)
|
||||
}
|
||||
err = m.GetDb().Where(sql, args...).Limit(limit, page).Find(&orders)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *ordersModel) CountAll(
|
||||
id int64,
|
||||
order_no string,
|
||||
merchant_id int64,
|
||||
product_id int64,
|
||||
out_trade_no string,
|
||||
recharge_account string,
|
||||
account_type int64,
|
||||
|
||||
status int64,
|
||||
transfer_status int64,
|
||||
startTime string,
|
||||
endTime string,
|
||||
) (res int64, err error) {
|
||||
sql := "1=1"
|
||||
var args []interface{}
|
||||
if id != 0 {
|
||||
sql += " and id = ?"
|
||||
args = append(args, id)
|
||||
}
|
||||
if order_no != "" {
|
||||
sql += " and order_no = ?"
|
||||
args = append(args, order_no)
|
||||
}
|
||||
if merchant_id != 0 {
|
||||
sql += " and merchant_id = ?"
|
||||
args = append(args, merchant_id)
|
||||
}
|
||||
if product_id != 0 {
|
||||
sql += " and merchant_id = ?"
|
||||
args = append(args, product_id)
|
||||
}
|
||||
if out_trade_no != "" {
|
||||
sql += " and out_trade_no = ?"
|
||||
args = append(args, out_trade_no)
|
||||
}
|
||||
if recharge_account != "" {
|
||||
sql += " and recharge_account = ?"
|
||||
args = append(args, recharge_account)
|
||||
}
|
||||
if account_type != 0 {
|
||||
sql += " and account_type = ?"
|
||||
args = append(args, recharge_account)
|
||||
}
|
||||
if status != 0 {
|
||||
sql += " and status = ?"
|
||||
args = append(args, status)
|
||||
}
|
||||
if transfer_status != 0 {
|
||||
sql += " and transfer_status = ?"
|
||||
args = append(args, transfer_status)
|
||||
}
|
||||
if startTime != "" && endTime != "" {
|
||||
sql += " and created_at >= ? and created_at <= ?"
|
||||
args = append(args, startTime, endTime)
|
||||
}
|
||||
res, err = m.GetDb().Where(sql, args...).Table("orders").Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (m *ordersModel) Create(orders *Orders) (affected int64, err error) {
|
||||
affected, err = m.GetDb().Insert(orders)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *ordersModel) Update(orders *Orders) (affected int64, err error) {
|
||||
affected, err = m.GetDb().ID(orders.Id).Update(orders)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *ordersModel) Delete(id int64) (affected int64, err error) {
|
||||
affected, err = m.GetDb().ID(id).Delete(&Orders{})
|
||||
return
|
||||
}
|
||||
|
||||
func (m *ordersModel) GetIdleOrder() (orders *Orders, has bool, err error) {
|
||||
orders = &Orders{}
|
||||
|
||||
session := m.GetDb().NewSession()
|
||||
defer session.Close()
|
||||
// add Begin() before any action
|
||||
if err = session.Begin(); err != nil {
|
||||
orders = nil
|
||||
return
|
||||
}
|
||||
|
||||
has, err = session.Where("transfer_status = 3").Limit(1).Get(orders)
|
||||
if err != nil || !has {
|
||||
orders = nil
|
||||
return
|
||||
}
|
||||
orders.TransferStatus = 2 // 1.成功 2.充值中 3. 等待充值 4.充值失败 5.异常需要人工处理
|
||||
affected, err := session.ID(orders.Id).Where("transfer_status = 3").Update(orders)
|
||||
if err != nil || affected == 0 {
|
||||
orders = nil
|
||||
return
|
||||
}
|
||||
err = session.Commit()
|
||||
return
|
||||
}
|
||||
|
||||
func (m *ordersModel) SetDealingOrder(orders *Orders) (affected int64, err error) {
|
||||
|
||||
session := m.GetDb().NewSession()
|
||||
defer session.Close()
|
||||
// add Begin() before any action
|
||||
if err = session.Begin(); err != nil {
|
||||
orders = nil
|
||||
return
|
||||
}
|
||||
|
||||
has, err := session.Where("id = ? and merchant_id = ? and product_id = ? and transfer_status = 2",
|
||||
orders.Id, orders.MerchantId, orders.ProductId).Get(&Orders{})
|
||||
if err != nil || !has {
|
||||
orders = nil
|
||||
return
|
||||
}
|
||||
// 1.成功 2.充值中 3. 等待充值 4.充值失败 5.异常需要人工处理
|
||||
affected, err = session.ID(orders.Id).Where("transfer_status = 2").Update(orders)
|
||||
if err != nil || affected == 0 {
|
||||
orders = nil
|
||||
return
|
||||
}
|
||||
err = session.Commit()
|
||||
return
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package product
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/qit-team/snow-core/db"
|
||||
)
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
m *productModel
|
||||
)
|
||||
|
||||
/**
|
||||
* Product
|
||||
*/
|
||||
type Product struct {
|
||||
Id int64 `xorm:"pk autoincr"` //注:使用getOne 或者ID() 需要设置主键
|
||||
Name string
|
||||
Price int64
|
||||
CreatedAt time.Time `xorm:"created"`
|
||||
}
|
||||
|
||||
/**
|
||||
* 表名规则
|
||||
* @wiki http://gobook.io/read/github.com/go-xorm/manual-zh-CN/chapter-02/3.tags.html
|
||||
*/
|
||||
func (m *Product) TableName() string {
|
||||
return "product"
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有化,防止被外部new
|
||||
*/
|
||||
type productModel struct {
|
||||
db.Model //组合基础Model,集成基础Model的属性和方法
|
||||
}
|
||||
|
||||
// 单例模式
|
||||
func GetInstance() *productModel {
|
||||
once.Do(func() {
|
||||
m = new(productModel)
|
||||
//m.DiName = "" //设置数据库实例连接,默认db.SingletonMain
|
||||
})
|
||||
return m
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询主键ID的记录
|
||||
* @param id 主键ID
|
||||
* @return has 是否有记录
|
||||
* @return err 错误信息
|
||||
* @return product 查询结果
|
||||
*/
|
||||
func (m *productModel) GetById(id int64) (product *Product, has bool, err error) {
|
||||
product = &Product{}
|
||||
has, err = m.GetDb().ID(id).Get(product)
|
||||
if err == nil || !has {
|
||||
product = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *productModel) Search(id int64, name string, startTime string, endTime string, limit int, page int) (product []*Product, err error) {
|
||||
product = make([]*Product, 0)
|
||||
sql := "1=1"
|
||||
var args []interface{}
|
||||
if id != 0 {
|
||||
sql += " and id = ?"
|
||||
args = append(args, id)
|
||||
}
|
||||
if name != "" {
|
||||
sql += " and name = ?"
|
||||
args = append(args, name)
|
||||
}
|
||||
if startTime != "" && endTime != "" {
|
||||
sql += " and created_at >= ? and created_at <= ?"
|
||||
args = append(args, startTime, endTime)
|
||||
}
|
||||
err = m.GetDb().Where(sql, args...).Limit(limit, page).Find(&product)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *productModel) CountAll(id int64, name string, startTime string, endTime string) (res int64, err error) {
|
||||
sql := "1=1"
|
||||
var args []interface{}
|
||||
if id != 0 {
|
||||
sql += " and id = ?"
|
||||
args = append(args, id)
|
||||
}
|
||||
if name != "" {
|
||||
sql += " and name = ?"
|
||||
args = append(args, name)
|
||||
}
|
||||
if startTime != "" && endTime != "" {
|
||||
sql += " and created_at >= ? and created_at <= ?"
|
||||
args = append(args, startTime, endTime)
|
||||
}
|
||||
res, err = m.GetDb().Table("product").Where(sql, args...).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (m *productModel) Create(product *Product) (affected int64, err error) {
|
||||
affected, err = m.GetDb().Insert(product)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *productModel) Update(product *Product) (affected int64, err error) {
|
||||
affected, err = m.GetDb().ID(product.Id).Update(product)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *productModel) Delete(id int64) (affected int64, err error) {
|
||||
affected, err = m.GetDb().ID(id).Delete(&Product{})
|
||||
return
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
package whitelist
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/qit-team/snow-core/db"
|
||||
)
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
m *whitelistModel
|
||||
)
|
||||
|
||||
/**
|
||||
* Whitelist
|
||||
*/
|
||||
type Whitelist struct {
|
||||
Id int64 `xorm:"pk autoincr"` //注:使用getOne 或者ID() 需要设置主键
|
||||
MerchantId int64
|
||||
Ip string
|
||||
CreatedAt time.Time `xorm:"created"`
|
||||
}
|
||||
|
||||
/**
|
||||
* 表名规则
|
||||
* @wiki http://gobook.io/read/github.com/go-xorm/manual-zh-CN/chapter-02/3.tags.html
|
||||
*/
|
||||
func (m *Whitelist) TableName() string {
|
||||
return "whitelist"
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有化,防止被外部new
|
||||
*/
|
||||
type whitelistModel struct {
|
||||
db.Model //组合基础Model,集成基础Model的属性和方法
|
||||
}
|
||||
|
||||
// 单例模式
|
||||
func GetInstance() *whitelistModel {
|
||||
once.Do(func() {
|
||||
m = new(whitelistModel)
|
||||
//m.DiName = "" //设置数据库实例连接,默认db.SingletonMain
|
||||
})
|
||||
return m
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询主键ID的记录
|
||||
* @param id 主键ID
|
||||
* @return has 是否有记录
|
||||
* @return err 错误信息
|
||||
* @return whitelist 查询结果
|
||||
*/
|
||||
func (m *whitelistModel) GetById(id int64) (whitelist *Whitelist, has bool, err error) {
|
||||
whitelist = &Whitelist{}
|
||||
has, err = m.GetDb().ID(id).Get(whitelist)
|
||||
if err == nil || !has {
|
||||
whitelist = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *whitelistModel) GetByIp(ip string) (whitelist *Whitelist, has bool, err error) {
|
||||
whitelist = &Whitelist{}
|
||||
has, err = m.GetDb().Where("ip = ?", ip).Get(whitelist)
|
||||
if err == nil || !has {
|
||||
whitelist = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *whitelistModel) Search(id int64, merchant_id int64, ip string, startTime string, endTime string, limit int, page int) (whitelist []*Whitelist, err error) {
|
||||
whitelist = make([]*Whitelist, 0)
|
||||
sql := "1=1"
|
||||
var args []interface{}
|
||||
if id != 0 {
|
||||
sql += " and id = ?"
|
||||
args = append(args, id)
|
||||
}
|
||||
if merchant_id != 0 {
|
||||
sql += " and merchant_id = ?"
|
||||
args = append(args, merchant_id)
|
||||
}
|
||||
if ip != "" {
|
||||
sql += " and ip = ?"
|
||||
args = append(args, ip)
|
||||
}
|
||||
if startTime != "" && endTime != "" {
|
||||
sql += " and created_at >= ? and created_at <= ?"
|
||||
args = append(args, startTime, endTime)
|
||||
}
|
||||
err = m.GetDb().Where(sql, args...).Limit(limit, page).Find(&whitelist)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *whitelistModel) CountAll(id int64, merchant_id int64, ip string, startTime string, endTime string) (res int64, err error) {
|
||||
sql := "1=1"
|
||||
var args []interface{}
|
||||
if id != 0 {
|
||||
sql += " and id = ?"
|
||||
args = append(args, id)
|
||||
}
|
||||
if merchant_id != 0 {
|
||||
sql += " and merchant_id = ?"
|
||||
args = append(args, merchant_id)
|
||||
}
|
||||
if ip != "" {
|
||||
sql += " and ip = ?"
|
||||
args = append(args, ip)
|
||||
}
|
||||
if startTime != "" && endTime != "" {
|
||||
sql += " and created_at >= ? and created_at <= ?"
|
||||
args = append(args, startTime, endTime)
|
||||
}
|
||||
res, err = m.GetDb().Table("whitelist").Where(sql, args...).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (m *whitelistModel) Create(whitelist *Whitelist) (affected int64, err error) {
|
||||
affected, err = m.GetDb().Insert(whitelist)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *whitelistModel) Update(whitelist *Whitelist) (affected int64, err error) {
|
||||
affected, err = m.GetDb().ID(whitelist.Id).Update(whitelist)
|
||||
return
|
||||
}
|
||||
|
||||
func (m *whitelistModel) Delete(id int64) (affected int64, err error) {
|
||||
affected, err = m.GetDb().ID(id).Delete(&Whitelist{})
|
||||
return
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package bannerservice
|
||||
|
||||
import (
|
||||
"com.snow.auto_monitor/app/models/bannermodel"
|
||||
)
|
||||
|
||||
func GetListByPid(pid int, limit int, page int) (banners []*bannermodel.Banner, err error) {
|
||||
limitStart := GetLimitStart(limit, page)
|
||||
banners, err = bannermodel.GetInstance().GetListByPid(pid, limitStart...)
|
||||
return
|
||||
}
|
||||
|
||||
func GetLimitStart(limit int, page int) (arr []int) {
|
||||
arr = make([]int, 2)
|
||||
if limit <= 0 {
|
||||
limit = 20
|
||||
}
|
||||
arr[0] = limit
|
||||
if page > 0 {
|
||||
arr[1] = (page - 1) * limit
|
||||
} else {
|
||||
arr[1] = 0
|
||||
}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package merchant
|
||||
|
||||
import (
|
||||
models "com.snow.auto_monitor/app/models/merchant"
|
||||
)
|
||||
|
||||
func GetLimitStart(limit int, page int) (int, int) {
|
||||
if limit <= 0 {
|
||||
limit = 20
|
||||
}
|
||||
if page > 0 {
|
||||
page = (page - 1) * limit
|
||||
} else {
|
||||
page = 0
|
||||
}
|
||||
return limit, page
|
||||
}
|
||||
|
||||
func GetById(id int64) (res *models.Merchant, err error) {
|
||||
res, _, err = models.GetInstance().GetById(id)
|
||||
return
|
||||
}
|
||||
|
||||
func Search(id int64, name string, startTime string, endTime string, limit int, page int) (res []*models.Merchant, err error) {
|
||||
limit, page = GetLimitStart(limit, page)
|
||||
res, err = models.GetInstance().Search(id, name, startTime, endTime, limit, page)
|
||||
return
|
||||
}
|
||||
|
||||
func CountAll(id int64, name string, startTime string, endTime string) (res int64, err error) {
|
||||
res, err = models.GetInstance().CountAll(id, name, startTime, endTime)
|
||||
return
|
||||
}
|
||||
|
||||
func Create(merchant *models.Merchant) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Create(merchant)
|
||||
return
|
||||
}
|
||||
|
||||
func Update(merchant *models.Merchant) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Update(merchant)
|
||||
return
|
||||
}
|
||||
|
||||
func Delete(id int64) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Delete(id)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package orders
|
||||
|
||||
import (
|
||||
models "com.snow.auto_monitor/app/models/orders"
|
||||
)
|
||||
|
||||
func GetLimitStart(limit int, page int) (int, int) {
|
||||
if limit <= 0 {
|
||||
limit = 20
|
||||
}
|
||||
if page > 0 {
|
||||
page = (page - 1) * limit
|
||||
} else {
|
||||
page = 0
|
||||
}
|
||||
return limit, page
|
||||
}
|
||||
|
||||
func GetById(id int64) (res *models.Orders, err error) {
|
||||
res, _, err = models.GetInstance().GetById(id)
|
||||
return
|
||||
}
|
||||
|
||||
func Search(id int64,
|
||||
order_no string,
|
||||
merchant_id int64,
|
||||
product_id int64,
|
||||
out_trade_no string,
|
||||
recharge_account string,
|
||||
account_type int64,
|
||||
|
||||
status int64,
|
||||
transfer_status int64,
|
||||
startTime string,
|
||||
endTime string,
|
||||
limit int,
|
||||
page int) (res []*models.Orders, err error) {
|
||||
limit, page = GetLimitStart(limit, page)
|
||||
res, err = models.GetInstance().Search(id, order_no, merchant_id, product_id, out_trade_no,
|
||||
recharge_account, account_type, status, transfer_status,
|
||||
startTime, endTime, limit, page)
|
||||
return
|
||||
}
|
||||
|
||||
func CountAll(id int64,
|
||||
order_no string,
|
||||
merchant_id int64,
|
||||
product_id int64,
|
||||
out_trade_no string,
|
||||
recharge_account string,
|
||||
account_type int64,
|
||||
|
||||
status int64,
|
||||
transfer_status int64,
|
||||
startTime string,
|
||||
endTime string) (res int64, err error) {
|
||||
res, err = models.GetInstance().CountAll(id, order_no, merchant_id, product_id, out_trade_no,
|
||||
recharge_account, account_type, status, transfer_status,
|
||||
startTime, endTime)
|
||||
return
|
||||
}
|
||||
|
||||
func Create(orders *models.Orders) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Create(orders)
|
||||
return
|
||||
}
|
||||
|
||||
func Update(orders *models.Orders) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Update(orders)
|
||||
return
|
||||
}
|
||||
|
||||
func Delete(id int64) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Delete(id)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package product
|
||||
|
||||
import (
|
||||
models "com.snow.auto_monitor/app/models/product"
|
||||
)
|
||||
|
||||
func GetLimitStart(limit int, page int) (int, int) {
|
||||
if limit <= 0 {
|
||||
limit = 20
|
||||
}
|
||||
if page > 0 {
|
||||
page = (page - 1) * limit
|
||||
} else {
|
||||
page = 0
|
||||
}
|
||||
return limit, page
|
||||
}
|
||||
|
||||
func GetById(id int64) (res *models.Product, err error) {
|
||||
res, _, err = models.GetInstance().GetById(id)
|
||||
return
|
||||
}
|
||||
|
||||
func Search(id int64, name string, startTime string, endTime string, limit int, page int) (res []*models.Product, err error) {
|
||||
limit, page = GetLimitStart(limit, page)
|
||||
res, err = models.GetInstance().Search(id, name, startTime, endTime, limit, page)
|
||||
return
|
||||
}
|
||||
|
||||
func CountAll(id int64, name string, startTime string, endTime string) (res int64, err error) {
|
||||
res, err = models.GetInstance().CountAll(id, name, startTime, endTime)
|
||||
return
|
||||
}
|
||||
|
||||
func Create(product *models.Product) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Create(product)
|
||||
return
|
||||
}
|
||||
|
||||
func Update(product *models.Product) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Update(product)
|
||||
return
|
||||
}
|
||||
|
||||
func Delete(id int64) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Delete(id)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package transfersys
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
mermod "com.snow.auto_monitor/app/models/merchant"
|
||||
models "com.snow.auto_monitor/app/models/orders"
|
||||
promod "com.snow.auto_monitor/app/models/product"
|
||||
)
|
||||
|
||||
func GetOrder() (res *models.Orders, err error) {
|
||||
res, _, err = models.GetInstance().GetIdleOrder()
|
||||
return
|
||||
}
|
||||
|
||||
func FinishOrder(orders *models.Orders) (affected int64, err error) {
|
||||
//验证商户是否存在
|
||||
_, has, err := mermod.GetInstance().GetById(orders.MerchantId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !has {
|
||||
err = errors.New("商户不存在")
|
||||
return
|
||||
}
|
||||
|
||||
//验证产品是否存在
|
||||
_, has, err = promod.GetInstance().GetById(orders.ProductId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !has {
|
||||
err = errors.New("产品不存在")
|
||||
return
|
||||
}
|
||||
|
||||
affected, err = models.GetInstance().SetDealingOrder(orders)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package transfersys
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
models "com.snow.auto_monitor/app/models/orders"
|
||||
rdbmq "com.snow.auto_monitor/app/utils/rdbmq"
|
||||
)
|
||||
|
||||
// func TestRDB() (err error) {
|
||||
// rdbmq.CreateGroup("orders", "orders_one")
|
||||
// return
|
||||
// }
|
||||
|
||||
// func WriteGroup() (err error) {
|
||||
// err = rdbmq.WriteOne("orders", time.Now().Format("2006-01-02 15:04:05"), "test")
|
||||
// return
|
||||
// }
|
||||
|
||||
func ReadGroup() (order *models.Orders, err error) {
|
||||
res, err := rdbmq.ReadOne("orders", "orders_one", "cosumer_one")
|
||||
if err != nil {
|
||||
if err.Error() == "context deadline exceeded" {
|
||||
return nil, errors.New("no data")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
key := ""
|
||||
for k := range res {
|
||||
key = k
|
||||
break
|
||||
}
|
||||
jsonstr := res[key].(string)
|
||||
json.Unmarshal([]byte(jsonstr), &order)
|
||||
return order, nil
|
||||
}
|
||||
|
||||
func WriteOrder() {
|
||||
fmt.Println("开始执行周期任务:getWxTransferStatus")
|
||||
// 创建分组
|
||||
err := rdbmq.CreateStreamAndGroup("orders", "orders_one")
|
||||
if err != nil && err.Error() != "BUSYGROUP Consumer Group name already exists" {
|
||||
fmt.Println("分组失败")
|
||||
return
|
||||
}
|
||||
// 创建一个新的Ticker,每3秒钟触发一次
|
||||
ticker := time.NewTicker(3 * time.Second)
|
||||
defer ticker.Stop() // 在函数结束时停止Ticker
|
||||
for range ticker.C {
|
||||
for i := 0; i < 10; i++ {
|
||||
res, _, err := models.GetInstance().GetIdleOrder()
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
continue
|
||||
}
|
||||
if res != nil {
|
||||
err = rdbmq.WriteOne("orders", res.OrderNo, res)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
go WriteOrder()
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package whitelist
|
||||
|
||||
import (
|
||||
models "com.snow.auto_monitor/app/models/whitelist"
|
||||
)
|
||||
|
||||
func GetLimitStart(limit int, page int) (int, int) {
|
||||
if limit <= 0 {
|
||||
limit = 20
|
||||
}
|
||||
if page > 0 {
|
||||
page = (page - 1) * limit
|
||||
} else {
|
||||
page = 0
|
||||
}
|
||||
return limit, page
|
||||
}
|
||||
|
||||
func GetById(id int64) (res *models.Whitelist, err error) {
|
||||
res, _, err = models.GetInstance().GetById(id)
|
||||
return
|
||||
}
|
||||
|
||||
func Search(id int64, merchant_id int64, ip string, startTime string, endTime string, limit int, page int) (res []*models.Whitelist, err error) {
|
||||
limit, page = GetLimitStart(limit, page)
|
||||
res, err = models.GetInstance().Search(id, merchant_id, ip, startTime, endTime, limit, page)
|
||||
return
|
||||
}
|
||||
|
||||
func CountAll(id int64, merchant_id int64, ip string, startTime string, endTime string) (res int64, err error) {
|
||||
res, err = models.GetInstance().CountAll(id, merchant_id, ip, startTime, endTime)
|
||||
return
|
||||
}
|
||||
|
||||
func Create(whitelist *models.Whitelist) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Create(whitelist)
|
||||
return
|
||||
}
|
||||
|
||||
func Update(whitelist *models.Whitelist) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Update(whitelist)
|
||||
return
|
||||
}
|
||||
|
||||
func Delete(id int64) (affected int64, err error) {
|
||||
affected, err = models.GetInstance().Delete(id)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package orders
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
models "com.snow.auto_monitor/app/models/orders"
|
||||
promod "com.snow.auto_monitor/app/models/product"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func GetByOutTradeNo(out_trade_no string, merchant_id int64) (res *models.Orders, err error) {
|
||||
res, _, err = models.GetInstance().GetByOutTradeNo(out_trade_no, merchant_id)
|
||||
return
|
||||
}
|
||||
|
||||
func CreateOrder(orders *models.Orders) (affected int64, err error) {
|
||||
//验证商户是否存在
|
||||
// _, has, err := mermod.GetInstance().GetById(orders.MerchantId)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// if !has {
|
||||
// err = errors.New("商户不存在")
|
||||
// return
|
||||
// }
|
||||
|
||||
//验证产品是否存在
|
||||
_, has, err := promod.GetInstance().GetById(orders.ProductId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !has {
|
||||
err = errors.New("产品不存在")
|
||||
return
|
||||
}
|
||||
//创建订单
|
||||
orders.OrderNo = uuid.New().String()
|
||||
orders.Status = 2 // 1.成功 2.充值中 3.充值失败 4.异常需要人工处理
|
||||
orders.TransferStatus = 3 // 1.成功 2.充值中 3. 等待充值 4.充值失败 5.异常需要人工处理
|
||||
affected, err = models.GetInstance().Create(orders)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
package httpclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"com.snow.auto_monitor/app/http/trace"
|
||||
"com.snow.auto_monitor/config"
|
||||
|
||||
"github.com/SkyAPM/go2sky"
|
||||
"github.com/SkyAPM/go2sky/propagation"
|
||||
v3 "github.com/SkyAPM/go2sky/reporter/grpc/language-agent"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/qit-team/snow-core/log/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
RetryCounts = 2
|
||||
RetryInterval = 3 * time.Second
|
||||
)
|
||||
|
||||
const componentIDGOHttpClient = 5005
|
||||
|
||||
type ClientConfig struct {
|
||||
ctx context.Context
|
||||
client *resty.Client
|
||||
tracer *go2sky.Tracer
|
||||
extraTags map[string]string
|
||||
}
|
||||
|
||||
type ClientOption func(*ClientConfig)
|
||||
|
||||
func WithClientTag(key string, value string) ClientOption {
|
||||
return func(c *ClientConfig) {
|
||||
if c.extraTags == nil {
|
||||
c.extraTags = make(map[string]string)
|
||||
}
|
||||
c.extraTags[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
func WithClient(client *resty.Client) ClientOption {
|
||||
return func(c *ClientConfig) {
|
||||
c.client = client
|
||||
}
|
||||
}
|
||||
|
||||
func WithContext(ctx context.Context) ClientOption {
|
||||
return func(c *ClientConfig) {
|
||||
c.ctx = ctx
|
||||
}
|
||||
}
|
||||
|
||||
type transport struct {
|
||||
*ClientConfig
|
||||
delegated http.RoundTripper
|
||||
}
|
||||
|
||||
func (t *transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
|
||||
span, err := t.tracer.CreateExitSpan(t.ctx, fmt.Sprintf("/%s%s", req.Method, req.URL.Path), req.Host, func(header string) error {
|
||||
// 将本层的调用链信息写入http头部, 传入到下一层调用, 当前使用v3版本的协议
|
||||
// https://github.com/apache/skywalking/blob/master/docs/en/protocols/Skywalking-Cross-Process-Propagation-Headers-Protocol-v3.md
|
||||
req.Header.Set(propagation.Header, header)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return t.delegated.RoundTrip(req)
|
||||
}
|
||||
defer span.End()
|
||||
span.SetComponent(componentIDGOHttpClient)
|
||||
for k, v := range t.extraTags {
|
||||
span.Tag(go2sky.Tag(k), v)
|
||||
}
|
||||
span.Tag(go2sky.TagHTTPMethod, req.Method)
|
||||
span.Tag(go2sky.TagURL, req.URL.String())
|
||||
span.SetSpanLayer(v3.SpanLayer_Http)
|
||||
resp, err = t.delegated.RoundTrip(req)
|
||||
if err != nil {
|
||||
span.Error(time.Now(), err.Error())
|
||||
return
|
||||
}
|
||||
span.Tag(go2sky.TagStatusCode, strconv.Itoa(resp.StatusCode))
|
||||
if resp.StatusCode >= http.StatusBadRequest {
|
||||
span.Error(time.Now(), "Errors on handling client")
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func NewClient(ctx context.Context, options ...ClientOption) (client *resty.Client) {
|
||||
client = resty.New()
|
||||
if config.IsDebug() {
|
||||
client.SetDebug(true).EnableTrace()
|
||||
}
|
||||
|
||||
var (
|
||||
tracer *go2sky.Tracer
|
||||
err error
|
||||
)
|
||||
if len(config.GetConf().SkyWalkingOapServer) > 0 && config.IsEnvEqual(config.ProdEnv) {
|
||||
tracer, err = trace.Tracer()
|
||||
if err != nil {
|
||||
logger.Error(ctx, "NewClient:Tracer", err.Error())
|
||||
}
|
||||
}
|
||||
if tracer != nil {
|
||||
co := &ClientConfig{ctx: ctx, tracer: tracer}
|
||||
for _, option := range options {
|
||||
option(co)
|
||||
}
|
||||
if co.client == nil {
|
||||
co.client = client
|
||||
}
|
||||
tp := &transport{
|
||||
ClientConfig: co,
|
||||
delegated: http.DefaultTransport,
|
||||
}
|
||||
if co.client.GetClient().Transport != nil {
|
||||
tp.delegated = co.client.GetClient().Transport
|
||||
}
|
||||
co.client.SetTransport(tp)
|
||||
}
|
||||
|
||||
client.OnBeforeRequest(func(ct *resty.Client, req *resty.Request) error {
|
||||
//req.SetContext(c)
|
||||
logger.Info(ctx, "OnBeforeRequest", logger.NewWithField("url", req.URL))
|
||||
return nil // if its success otherwise return error
|
||||
})
|
||||
// Registering Response Middleware
|
||||
client.OnAfterResponse(func(ct *resty.Client, resp *resty.Response) error {
|
||||
logger.Info(ctx, "OnAfterResponse", logger.NewWithField("url", resp.Request.URL), logger.NewWithField("request", resp.Request.RawRequest), logger.NewWithField("response", resp.String()))
|
||||
return nil
|
||||
})
|
||||
return client
|
||||
}
|
||||
|
||||
func NewClientWithRetry(ctx context.Context, retryCounts int, retryInterval time.Duration, options ...ClientOption) (client *resty.Client) {
|
||||
client = resty.New()
|
||||
if config.IsDebug() {
|
||||
client.SetDebug(true).EnableTrace()
|
||||
}
|
||||
if retryCounts == 0 {
|
||||
retryCounts = RetryCounts
|
||||
}
|
||||
if retryInterval.Seconds() == 0.0 {
|
||||
retryInterval = RetryInterval
|
||||
}
|
||||
client.SetRetryCount(retryCounts).SetRetryMaxWaitTime(retryInterval)
|
||||
|
||||
var (
|
||||
tracer *go2sky.Tracer
|
||||
err error
|
||||
)
|
||||
if len(config.GetConf().SkyWalkingOapServer) > 0 && config.IsEnvEqual(config.ProdEnv) {
|
||||
tracer, err = trace.Tracer()
|
||||
if err != nil {
|
||||
logger.Error(ctx, "NewClient:Tracer", err.Error())
|
||||
}
|
||||
}
|
||||
if tracer != nil {
|
||||
co := &ClientConfig{ctx: ctx, tracer: tracer}
|
||||
for _, option := range options {
|
||||
option(co)
|
||||
}
|
||||
if co.client == nil {
|
||||
co.client = client
|
||||
}
|
||||
tp := &transport{
|
||||
ClientConfig: co,
|
||||
delegated: http.DefaultTransport,
|
||||
}
|
||||
if co.client.GetClient().Transport != nil {
|
||||
tp.delegated = co.client.GetClient().Transport
|
||||
}
|
||||
co.client.SetTransport(tp)
|
||||
}
|
||||
|
||||
client.OnBeforeRequest(func(ct *resty.Client, req *resty.Request) error {
|
||||
logger.Info(ctx, "OnBeforeRequest", logger.NewWithField("url", req.URL))
|
||||
return nil // if its success otherwise return error
|
||||
})
|
||||
// Registering Response Middleware
|
||||
client.OnAfterResponse(func(ct *resty.Client, resp *resty.Response) error {
|
||||
logger.Info(ctx, "OnAfterResponse", logger.NewWithField("url", resp.Request.URL), logger.NewWithField("request", resp.Request.RawRequest), logger.NewWithField("response", resp.String()))
|
||||
return nil
|
||||
})
|
||||
return client
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
package metric
|
||||
|
||||
// prometheus metric:unique identifier: name and optional key-value pairs called labels
|
||||
// 1. name regexp: [a-zA-Z_:][a-zA-Z0-9_:]*
|
||||
// 2. label name regexp: [a-zA-Z_][a-zA-Z0-9_]*
|
||||
// 3. Label names beginning with __ are reserved for internal use.
|
||||
// 4. Label values may contain any Unicode characters.
|
||||
// 5. notation: <metric name>{<label name>=<label value>, ...}
|
||||
// for example: api_http_requests_total{method="POST", handler="/messages"}
|
||||
// A label with an empty label value is considered equivalent to a label that does not exist.
|
||||
|
||||
// each sample consists of :
|
||||
// - a float64 value
|
||||
// - a millisecond-precision timestamp
|
||||
|
||||
// metric type:
|
||||
// - Counter
|
||||
// A cumulative metric that represents a single monotonically increasing counter whose value can only increase or be reset to zero on restart.
|
||||
// - Gauge
|
||||
// A gauge is a metric that represents a single numerical value that can arbitrarily go up and down.
|
||||
// - Histogram
|
||||
// A histogram samples observations (usually things like request durations or response sizes) and counts them in configurable buckets. It also provides a sum of all observed values.
|
||||
// - Summary
|
||||
// Similar to a histogram, a summary samples observations (usually things like request durations and response sizes). While it also provides a total count of observations and a sum of all observed values, it calculates configurable quantiles over a sliding time window.
|
||||
// metric:
|
||||
// Counter:
|
||||
// - req_total_count
|
||||
// - req_failed_count
|
||||
// Gauge:
|
||||
// - heap_inuse_size
|
||||
// - heap_total_size
|
||||
// - heap_object_num
|
||||
// - goroutine_num
|
||||
// Histogram:
|
||||
// - req_cost_time
|
||||
// Summary:
|
||||
// - req_cost_time
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
const (
|
||||
//ENV = "env"
|
||||
APP = "snow"
|
||||
VER = "ver"
|
||||
)
|
||||
|
||||
var (
|
||||
collectors = []prometheus.Collector{}
|
||||
)
|
||||
|
||||
func RegisterCollector(c ...prometheus.Collector) {
|
||||
collectors = append(collectors, c...)
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
labels map[string]string
|
||||
processEnable bool
|
||||
runtimeEnable bool
|
||||
}
|
||||
|
||||
type Option func(opt *Options)
|
||||
|
||||
// 添加App和Ver label
|
||||
func AppVer(app, ver string) Option {
|
||||
return func(opt *Options) {
|
||||
if app != "" {
|
||||
opt.labels[APP] = app
|
||||
}
|
||||
if ver != "" {
|
||||
opt.labels[VER] = ver
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加额外label
|
||||
func WithLabel(key, val string) Option {
|
||||
return func(opt *Options) {
|
||||
if key != "" && val != "" {
|
||||
opt.labels[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 收集进程信息
|
||||
func EnableProcess() Option {
|
||||
return func(opt *Options) {
|
||||
opt.processEnable = true
|
||||
}
|
||||
}
|
||||
|
||||
func EnableRuntime() Option {
|
||||
return func(opt *Options) {
|
||||
opt.runtimeEnable = true
|
||||
}
|
||||
}
|
||||
|
||||
type Reporter struct {
|
||||
opts Options
|
||||
collectors []prometheus.Collector
|
||||
// registerer
|
||||
registerer prometheus.Registerer
|
||||
gatherer prometheus.Gatherer
|
||||
}
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
reporter Reporter
|
||||
)
|
||||
|
||||
func Init(opts ...Option) {
|
||||
_opts := Options{
|
||||
labels: map[string]string{},
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(&_opts)
|
||||
}
|
||||
|
||||
once.Do(func() {
|
||||
cs := collectors
|
||||
if _opts.processEnable {
|
||||
cs = append(cs, prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}))
|
||||
}
|
||||
|
||||
if _opts.runtimeEnable {
|
||||
cs = append(cs, prometheus.NewGoCollector())
|
||||
}
|
||||
|
||||
reporter = Reporter{
|
||||
opts: _opts,
|
||||
collectors: cs,
|
||||
}
|
||||
|
||||
registry := prometheus.NewRegistry()
|
||||
|
||||
reporter.registerer = prometheus.WrapRegistererWith(reporter.opts.labels, registry)
|
||||
reporter.gatherer = registry
|
||||
|
||||
reporter.registerer.MustRegister(reporter.collectors...)
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (p *Reporter) newCounterVec(metric string, labels []string) *prometheus.CounterVec {
|
||||
counterVec := prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: metric,
|
||||
}, labels)
|
||||
|
||||
return counterVec
|
||||
}
|
||||
|
||||
func (p *Reporter) newGaugeVec(metric string, labels []string) *prometheus.GaugeVec {
|
||||
gaugeVec := prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Name: metric,
|
||||
}, labels)
|
||||
return gaugeVec
|
||||
}
|
||||
|
||||
func (p *Reporter) newHistogramVec(metric string, labels []string, buckets []float64) *prometheus.HistogramVec {
|
||||
histogramVec := prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: metric,
|
||||
Buckets: buckets,
|
||||
}, labels)
|
||||
return histogramVec
|
||||
}
|
||||
|
||||
func Handler() http.Handler {
|
||||
return promhttp.InstrumentMetricHandler(
|
||||
reporter.registerer, promhttp.HandlerFor(reporter.gatherer, promhttp.HandlerOpts{}),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package rdbmq
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"com.snow.auto_monitor/config"
|
||||
goredis "github.com/go-redis/redis/v8"
|
||||
"github.com/qit-team/snow-core/redis"
|
||||
)
|
||||
|
||||
// const Nil = goredis.
|
||||
|
||||
func init() {
|
||||
//加载配置文件
|
||||
conf, err := config.Load("./.env")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
//注册redis类
|
||||
err = redis.Pr.Register(redis.SingletonMain, conf.Redis)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func CreateStreamAndGroup(stream string, group string) (err error) {
|
||||
rdb := redis.GetRedis(redis.SingletonMain)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
// 创建stream和group
|
||||
err = rdb.XGroupCreateMkStream(ctx, stream, group, "$").Err()
|
||||
|
||||
// XGroupCreate,创建一个消费者组
|
||||
// err = rdb.XGroupCreate(ctx, stream, group, "$").Err()
|
||||
return
|
||||
}
|
||||
|
||||
func WriteOne(stream string, key string, value interface{}) (err error) {
|
||||
rdb := redis.GetRedis(redis.SingletonMain)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
|
||||
defer cancel()
|
||||
// XADD,添加消息到对尾(这个代码每运行一次就增加一次内容)
|
||||
err = rdb.XAdd(ctx, &goredis.XAddArgs{
|
||||
Stream: stream, // 设置流stream的 key,消息队列名
|
||||
NoMkStream: false, //为false,key不存在会新建
|
||||
MaxLen: 10000, //消息队列最大长度,队列长度超过设置最大长度后,旧消息会被删除
|
||||
Approx: false, //默认false,设为true时,模糊指定stram的长度
|
||||
ID: "*", //消息ID,* 表示由Redis自动生成
|
||||
Values: []interface{}{ //消息队列的内容,键值对形式
|
||||
key, value,
|
||||
},
|
||||
// MinID: "id",//超过设置长度值,丢弃小于MinID消息id
|
||||
// Limit: 1000, //限制长度,基本不用
|
||||
}).Err()
|
||||
return
|
||||
}
|
||||
|
||||
func ReadOne(stream string, group string, consumer string) (res map[string]interface{}, err error) {
|
||||
rdb := redis.GetRedis(redis.SingletonMain)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
// XReadGroup,读取消费者中消息
|
||||
readgroupval, err := rdb.XReadGroup(ctx, &goredis.XReadGroupArgs{
|
||||
// Streams第二个参数为ID,list of streams and ids, e.g. stream1 stream2 id1 id2
|
||||
// id为 >,表示最新未读消息ID,也是未被分配给其他消费者的最新消息
|
||||
// id为 0 或其他,表示可以获取已读但未确认的消息。这种情况下BLOCK和NOACK都会忽略
|
||||
// id为具体ID,表示获取这个消费者组的pending的历史消息,而不是新消息
|
||||
Streams: []string{stream, ">"},
|
||||
Group: group, //消费者组名
|
||||
Consumer: consumer, // 消费者名
|
||||
Count: 1,
|
||||
Block: 0,
|
||||
NoAck: true, // true-表示读取消息时确认消息
|
||||
}).Result()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return readgroupval[0].Messages[0].Values, err
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package bootstrap
|
||||
|
||||
import (
|
||||
"com.snow.auto_monitor/app/jobs"
|
||||
"com.snow.auto_monitor/app/jobs/basejob"
|
||||
"com.snow.auto_monitor/config"
|
||||
|
||||
"github.com/qit-team/snow-core/db"
|
||||
"github.com/qit-team/snow-core/kernel/close"
|
||||
"github.com/qit-team/snow-core/kernel/container"
|
||||
"github.com/qit-team/snow-core/log/accesslogger"
|
||||
"github.com/qit-team/snow-core/log/logger"
|
||||
"github.com/qit-team/snow-core/redis"
|
||||
)
|
||||
|
||||
//全局变量
|
||||
var App *container.Container
|
||||
|
||||
/**
|
||||
* 服务引导程序
|
||||
*/
|
||||
func Bootstrap(conf *config.Config) (err error) {
|
||||
//容器
|
||||
App = container.App
|
||||
|
||||
//注册db服务
|
||||
//第一个参数为注入别名,第二个参数为配置,第三个参数可选为是否懒加载
|
||||
err = db.Pr.Register(db.SingletonMain, conf.Db)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//注册redis服务
|
||||
err = redis.Pr.Register(redis.SingletonMain, conf.Redis)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//注册mns服务
|
||||
//err = alimns.Pr.Register(alimns.SingletonMain, conf.Mns, true)
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
|
||||
//注册日志类服务
|
||||
err = logger.Pr.Register(logger.SingletonMain, conf.Log, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//注册access log服务
|
||||
err = accesslogger.Pr.Register(accesslogger.SingletonMain, conf.Log)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//注册应用停止时调用的关闭服务
|
||||
close.MultiRegister(db.Pr, redis.Pr)
|
||||
|
||||
//注册job register,为了非job模式的消息入队调用
|
||||
basejob.SetJobRegister(jobs.RegisterWorker)
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
|
@ -0,0 +1,9 @@
|
|||
#/bin/bash
|
||||
os=$1 #系统linux
|
||||
arch=$2 #架构amd64
|
||||
|
||||
#回到根目录
|
||||
rootPath=$(cd `dirname $0`/../../; pwd)
|
||||
|
||||
#编译
|
||||
GOOS=$os GOARCH=$arch go build -o build/bin/snow main.go
|
|
@ -0,0 +1,38 @@
|
|||
create table merchant (
|
||||
id int primary key auto_increment,
|
||||
name varchar(255) not null,
|
||||
key varchar(255),
|
||||
created_at timestamp default current_timestamp
|
||||
);
|
||||
|
||||
create table orders (
|
||||
id int primary key auto_increment,
|
||||
order_no varchar(255) not null,
|
||||
merchant_id int,
|
||||
|
||||
out_trade_no varchar(64),
|
||||
product_id int,
|
||||
recharge_account varchar(64),
|
||||
account_type tinyint,
|
||||
number int,
|
||||
notify_url varchar(255),
|
||||
extend_parameter varchar(1024),
|
||||
|
||||
status tinyint,
|
||||
transfer_status tinyint,
|
||||
created_at timestamp default current_timestamp,
|
||||
);
|
||||
|
||||
create table whitelist (
|
||||
id int primary key auto_increment,
|
||||
merchant_id int,
|
||||
ip varchar(64),
|
||||
created_at timestamp default current_timestamp
|
||||
);
|
||||
|
||||
create table product (
|
||||
id int primary key auto_increment,
|
||||
name varchar(255) not null,
|
||||
price int,
|
||||
created_at timestamp default current_timestamp
|
||||
);
|
|
@ -0,0 +1,73 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/qit-team/snow-core/config"
|
||||
)
|
||||
|
||||
const (
|
||||
ProdEnv = "production" //线上环境
|
||||
BetaEnv = "beta" //beta环境
|
||||
DevEnv = "develop" //开发环境
|
||||
LocalEnv = "local" //本地环境
|
||||
)
|
||||
|
||||
var srvConf *Config
|
||||
|
||||
//------------------------配置文件解析
|
||||
type Config struct {
|
||||
ServiceName string `toml:"ServiceName"`
|
||||
Env string `toml:"Env"`
|
||||
Debug bool `toml:"Debug"`
|
||||
PrometheusCollectEnable bool `toml:"PrometheusCollectEnable"`
|
||||
SkyWalkingOapServer string `toml:"SkyWalkingOapServer"`
|
||||
Log config.LogConfig `toml:"Log"`
|
||||
Redis config.RedisConfig `toml:"Redis"`
|
||||
Mns config.MnsConfig `toml:"AliMns"`
|
||||
Db config.DbConfig `toml:"Db"`
|
||||
Api config.ApiConfig `toml:"Api"`
|
||||
}
|
||||
|
||||
func newConfig() *Config {
|
||||
return new(Config)
|
||||
}
|
||||
|
||||
//------------------------ 加载配置 ------------------------//
|
||||
func Load(path string) (*Config, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conf := newConfig()
|
||||
if _, err := toml.DecodeFile(path, conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
srvConf = conf
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
//当前配置
|
||||
func GetConf() *Config {
|
||||
return srvConf
|
||||
}
|
||||
|
||||
//是否调试模式
|
||||
func IsDebug() bool {
|
||||
return srvConf.Debug
|
||||
}
|
||||
|
||||
//当前环境,默认本地开发
|
||||
func GetEnv() string {
|
||||
if srvConf.Env == "" {
|
||||
return LocalEnv
|
||||
}
|
||||
return srvConf.Env
|
||||
}
|
||||
|
||||
//是否当前环境
|
||||
func IsEnvEqual(env string) bool {
|
||||
return GetEnv() == env
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var options *Options
|
||||
|
||||
//------------------------启动命令配置
|
||||
type Options struct {
|
||||
ShowVersion bool
|
||||
Cmd string
|
||||
ConfFile string
|
||||
App string
|
||||
PidDir string
|
||||
Queue string
|
||||
Command string
|
||||
}
|
||||
|
||||
func parseOptions() *Options {
|
||||
opts := new(Options)
|
||||
flag.BoolVar(&opts.ShowVersion, "v", false, "show version")
|
||||
flag.StringVar(&opts.App, "a", "api", "application to run")
|
||||
flag.StringVar(&opts.Cmd, "k", "", "status|stop|restart")
|
||||
flag.StringVar(&opts.ConfFile, "c", ".env", "conf file path")
|
||||
flag.StringVar(&opts.PidDir, "p", "/var/run/", "pid directory")
|
||||
flag.StringVar(&opts.Queue, "queue", "", "topic of queue is enable")
|
||||
flag.StringVar(&opts.Command, "m", "", "command name")
|
||||
flag.Parse()
|
||||
return opts
|
||||
}
|
||||
|
||||
//获取启动命令配置
|
||||
func GetOptions() *Options {
|
||||
if options == nil {
|
||||
options = parseOptions()
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
//pid进程号的保存路径
|
||||
func (opts *Options) GenPidFile() string {
|
||||
return strings.TrimRight(opts.PidDir, "/") + "/" + opts.App + ".pid"
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package docs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/alecthomas/template"
|
||||
"github.com/swaggo/swag"
|
||||
)
|
||||
|
||||
var doc =``
|
||||
|
||||
type swaggerInfo struct {
|
||||
Version string
|
||||
Host string
|
||||
BasePath string
|
||||
Schemes []string
|
||||
Title string
|
||||
Description string
|
||||
}
|
||||
|
||||
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
||||
var SwaggerInfo = swaggerInfo{ Schemes: []string{}}
|
||||
|
||||
type s struct{}
|
||||
|
||||
func (s *s) ReadDoc() string {
|
||||
t, err := template.New("swagger_info").Funcs(template.FuncMap{
|
||||
"marshal": func(v interface {}) string {
|
||||
a, _ := json.Marshal(v)
|
||||
return string(a)
|
||||
},
|
||||
}).Parse(doc)
|
||||
if err != nil {
|
||||
return doc
|
||||
}
|
||||
|
||||
var tpl bytes.Buffer
|
||||
if err := t.Execute(&tpl, SwaggerInfo); err != nil {
|
||||
return doc
|
||||
}
|
||||
|
||||
return tpl.String()
|
||||
}
|
||||
|
||||
func init() {
|
||||
swag.Register(swag.Name, &s{})
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
module com.snow.auto_monitor
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.4.1
|
||||
github.com/SkyAPM/go2sky v0.6.0
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
||||
github.com/gin-gonic/gin v1.7.7
|
||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||
github.com/go-openapi/swag v0.19.15 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.4
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
github.com/go-sql-driver/mysql v1.6.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/qit-team/snow-core v0.1.28
|
||||
github.com/qit-team/work v0.3.11
|
||||
github.com/robfig/cron v1.2.0
|
||||
github.com/swaggo/gin-swagger v1.3.3
|
||||
github.com/swaggo/swag v1.7.6
|
||||
gopkg.in/go-playground/validator.v9 v9.31.0
|
||||
)
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
|
@ -0,0 +1,122 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"com.snow.auto_monitor/app/console"
|
||||
"com.snow.auto_monitor/app/http/routes"
|
||||
"com.snow.auto_monitor/app/jobs"
|
||||
"com.snow.auto_monitor/bootstrap"
|
||||
"com.snow.auto_monitor/config"
|
||||
_ "com.snow.auto_monitor/docs"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/qit-team/snow-core/cache/rediscache"
|
||||
"github.com/qit-team/snow-core/kernel/server"
|
||||
_ "github.com/qit-team/snow-core/queue/redisqueue"
|
||||
)
|
||||
|
||||
// @title Swagger Example API
|
||||
// @version 1.0
|
||||
// @description This is a sample server celler server.
|
||||
// @termsOfService http://swagger.io/terms/
|
||||
|
||||
// @contact.name API Support
|
||||
// @contact.url http://www.swagger.io/support
|
||||
// @contact.email support@swagger.io
|
||||
|
||||
// @license.name Apache 2.0
|
||||
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
// @host localhost:8080
|
||||
// @BasePath /
|
||||
|
||||
// @securityDefinitions.basic BasicAuth
|
||||
|
||||
// @securityDefinitions.apikey ApiKeyAuth
|
||||
// @in header
|
||||
// @name Authorization
|
||||
|
||||
// @securitydefinitions.oauth2.application OAuth2Application
|
||||
// @tokenUrl https://example.com/oauth/token
|
||||
// @scope.write Grants write access
|
||||
// @scope.admin Grants read and write access to administrative information
|
||||
|
||||
// @securitydefinitions.oauth2.implicit OAuth2Implicit
|
||||
// @authorizationUrl https://example.com/oauth/authorize
|
||||
// @scope.write Grants write access
|
||||
// @scope.admin Grants read and write access to administrative information
|
||||
|
||||
// @securitydefinitions.oauth2.password OAuth2Password
|
||||
// @tokenUrl https://example.com/oauth/token
|
||||
// @scope.read Grants read access
|
||||
// @scope.write Grants write access
|
||||
// @scope.admin Grants read and write access to administrative information
|
||||
|
||||
// @securitydefinitions.oauth2.accessCode OAuth2AccessCode
|
||||
// @tokenUrl https://example.com/oauth/token
|
||||
// @authorizationUrl https://example.com/oauth/authorize
|
||||
// @scope.admin Grants read and write access to administrative information
|
||||
func main() {
|
||||
//解析启动命令
|
||||
opts := config.GetOptions()
|
||||
if opts.ShowVersion {
|
||||
fmt.Printf("%s\ncommit %s\nbuilt on %s\n", server.Version, server.BuildCommit, server.BuildDate)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
handleCmd(opts)
|
||||
|
||||
err := startServer(opts)
|
||||
if err != nil {
|
||||
fmt.Printf("server start error, %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
//执行(status|stop|restart)命令
|
||||
func handleCmd(opts *config.Options) {
|
||||
if opts.Cmd != "" {
|
||||
pidFile := opts.GenPidFile()
|
||||
err := server.HandleUserCmd(opts.Cmd, pidFile)
|
||||
if err != nil {
|
||||
fmt.Printf("Handle user command(%s) error, %s\n", opts.Cmd, err)
|
||||
} else {
|
||||
fmt.Printf("Handle user command(%s) succ \n ", opts.Cmd)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
func startServer(opts *config.Options) (err error) {
|
||||
//加载配置
|
||||
conf, err := config.Load(opts.ConfFile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//引导程序
|
||||
err = bootstrap.Bootstrap(conf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pidFile := opts.GenPidFile()
|
||||
|
||||
//根据启动命令行参数,决定启动哪种服务模式
|
||||
switch opts.App {
|
||||
case "api":
|
||||
err = server.StartHttp(pidFile, conf.Api, routes.RegisterRoute)
|
||||
case "cron":
|
||||
err = server.StartConsole(pidFile, console.RegisterSchedule)
|
||||
case "job":
|
||||
err = server.StartJob(pidFile, jobs.RegisterWorker)
|
||||
case "command":
|
||||
err = server.ExecuteCommand(opts.Command, console.RegisterCommand)
|
||||
default:
|
||||
err = errors.New("no server start")
|
||||
}
|
||||
return
|
||||
}
|
Loading…
Reference in New Issue