diff --git a/app/constants/errorcode/error_code.go b/app/constants/errorcode/error_code.go index f240f37..8df0f99 100644 --- a/app/constants/errorcode/error_code.go +++ b/app/constants/errorcode/error_code.go @@ -19,11 +19,19 @@ const ( //系统错误 SystemError = 500 + //请求超时 + RequestTimeOut = 600 + //未登录 NotLogin = 1000 // 商户 MerchantNotFound = 1100 + + // app + AppNotFound = 1200 + AppDisabled = 1201 + AppIpNotAllow = 1202 ) var MsgEN = map[int]string{ @@ -36,13 +44,16 @@ var MsgEN = map[int]string{ } var MsgZH = map[int]string{ - Success: "请求成功", - ParamError: "参数错误", - NotFound: "数据不存在", - NotAuth: "未经授权", - NotLogin: "未登录", - + Success: "请求成功", + ParamError: "参数错误", + NotFound: "数据不存在", + NotAuth: "未经授权", + NotLogin: "未登录", + RequestTimeOut: "请求超时", MerchantNotFound: "商户不存在", + AppNotFound: "app_id未找到", + AppDisabled: "app通道关闭", + AppIpNotAllow: "ip不在白名单内", } var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH} diff --git a/app/constants/pojo/app.go b/app/constants/pojo/app.go new file mode 100644 index 0000000..29f0239 --- /dev/null +++ b/app/constants/pojo/app.go @@ -0,0 +1,7 @@ +package pojo + +const ( + Rsa int32 = iota + 1 + Sm2 + Sm4 +) diff --git a/app/constants/pojo/common.go b/app/constants/pojo/common.go new file mode 100644 index 0000000..1e58d13 --- /dev/null +++ b/app/constants/pojo/common.go @@ -0,0 +1,6 @@ +package pojo + +const ( + STATUS_ENABLE int32 = 1 + STATUS_DISABLED int32 = 2 +) diff --git a/app/data/app.go b/app/data/app.go index ff8c0fa..f355d0f 100644 --- a/app/data/app.go +++ b/app/data/app.go @@ -3,6 +3,7 @@ package data import ( "PaymentCenter/app/http/entities" "PaymentCenter/app/models/appmodel" + "database/sql" "xorm.io/builder" "xorm.io/xorm" ) @@ -37,3 +38,12 @@ func (m *AppRepo) AppDelete(app *appmodel.App, conn builder.Cond) (int64, error) func (m *AppRepo) AppUpdate(app *appmodel.App, conn builder.Cond, columns ...string) (int64, error) { return m.repo.Where(conn).MustCols(columns...).Update(app) } + +func (m *AppRepo) AppFindOne(app *appmodel.App, conn builder.Cond, columns ...string) (*appmodel.App, error) { + has, err := m.repo.Where(conn).Get(app) + if !has { + return nil, sql.ErrNoRows + } + return app, err + +} diff --git a/app/http/controllers/base.go b/app/http/controllers/base.go index 354472c..e3b1196 100644 --- a/app/http/controllers/base.go +++ b/app/http/controllers/base.go @@ -207,3 +207,7 @@ func phoneValidation(fl validator.FieldLevel) bool { reg := regexp.MustCompile(phoneRegex) return reg.MatchString(phone) } + +func ErrWithCode(c *gin.Context, code int) { + Error(c, code, errorcode.GetMsg(code, c.GetHeader("local"))) +} diff --git a/app/http/entities/front/pay.go b/app/http/entities/front/pay.go index 6c90641..f3dca7a 100644 --- a/app/http/entities/front/pay.go +++ b/app/http/entities/front/pay.go @@ -1,8 +1,8 @@ package front type PayCommonBody struct { - AppId string `json:"app_id" validate:"required"` - Timestamp int64 `json:"timestamp" validate:"required"` + AppId int64 `json:"app_id" validate:"required"` + Timestamp int64 `json:"timestamp" validate:"required"` } type PayWeb struct { diff --git a/app/http/middlewares/base.go b/app/http/middlewares/base.go index 4bdaa62..929d595 100644 --- a/app/http/middlewares/base.go +++ b/app/http/middlewares/base.go @@ -4,8 +4,10 @@ import ( "PaymentCenter/app/constants/common" "PaymentCenter/app/constants/errorcode" "PaymentCenter/app/http/controllers" + "PaymentCenter/app/http/entities" "PaymentCenter/app/http/entities/front" "PaymentCenter/app/http/requestmapping" + "PaymentCenter/app/services" "PaymentCenter/app/utils" "context" "errors" @@ -109,9 +111,32 @@ func ValidatePayRequest() gin.HandlerFunc { return func(c *gin.Context) { com, err := utils.SonicApiDataToStruct(controllers.GetRequest(c), &front.PayCommonBody{}) if err != nil { - controllers.Error(c, errorcode.ParamError, err.Error()) + controllers.ErrWithCode(c, errorcode.ParamError) + } + comStruct := com.(*front.PayCommonBody) + //判断时间 + //now := time.Now().UnixNano() / 1000000 + //if comStruct.Timestamp > now || (config.GetConf().TimeOut != 0 && (now-comStruct.Timestamp) > config.GetConf().TimeOut) { + // controllers.ErrWithCode(c, errorcode.RequestTimeOut) + // return + //} + //获取app信息 + app, errCode := services.AppFindOne(entities.IdRequest{Id: comStruct.AppId}) + if errCode != errorcode.Success { + controllers.ErrWithCode(c, errCode) + return + } + //检查app可用性 + appCheck := services.NewAppCheck(app).Check() + if appCheck.GetCode() != errorcode.Success { + controllers.ErrWithCode(c, appCheck.GetCode()) + return + } + //检查白名单 + if !appCheck.IpCheck(c.ClientIP()) { + controllers.ErrWithCode(c, appCheck.GetCode()) + return } - com = com.(*front.PayCommonBody) c.Next() } diff --git a/app/models/appmodel/app.go b/app/models/appmodel/app.go index b840778..b1b008a 100644 --- a/app/models/appmodel/app.go +++ b/app/models/appmodel/app.go @@ -15,10 +15,10 @@ var ( type App struct { Id int64 MerchantId int64 `xorm:"'merchant_id' bigint(20)"` - AppName string `xorm:"'app_name' varchar(128)"` - AppRemark string `xorm:"'app_remark' varchar(255)"` - Status int `xorm:"'status' int(11)"` - KeyType int `xorm:"'key_type' int(11)"` + AppName string `xorm:"'app_name' varchar(20)"` + AppRemark string `xorm:"'app_remark' varchar(200)"` + Status int32 `xorm:"'status' tinyint(2)"` + KeyType int32 `xorm:"'key_type' tinyint(2)"` PublicKey string `xorm:"'public_key' varchar(1024)"` PrivateKey string `xorm:"'private_key' varchar(1024)"` MerchantPublicKey string `xorm:"'merchant_public_key' varchar(1024)"` diff --git a/app/services/api_request_valid.go b/app/services/api_request_valid.go index f448435..16cb09e 100644 --- a/app/services/api_request_valid.go +++ b/app/services/api_request_valid.go @@ -1,5 +1,47 @@ package services -func validIp(ip string) bool { +import ( + "PaymentCenter/app/constants/errorcode" + "PaymentCenter/app/constants/pojo" + "PaymentCenter/app/models/appmodel" + "PaymentCenter/app/utils" + "strings" +) + +type AppCheck struct { + App *appmodel.App + Code int +} + +func NewAppCheck(app *appmodel.App) *AppCheck { + return &AppCheck{ + App: app, + Code: errorcode.Success, + } +} + +func (a *AppCheck) IpCheck(ip string) bool { + if a.App.WhiteIp == "" { + return true + } + if !utils.ContainsString(strings.Split(a.App.WhiteIp, ","), ip) { + a.Code = errorcode.AppIpNotAllow + return false + } return true } + +func (a *AppCheck) Check() *AppCheck { + + if a.App.Status == pojo.STATUS_DISABLED { + a.Code = errorcode.AppDisabled + } + if a.App.DeleteTime.Location() == nil { + a.Code = errorcode.AppNotFound + } + return a +} + +func (a *AppCheck) GetCode() int { + return a.Code +} diff --git a/app/services/apicrypt/rsa.go b/app/services/apicrypt/rsa.go new file mode 100644 index 0000000..171271d --- /dev/null +++ b/app/services/apicrypt/rsa.go @@ -0,0 +1,17 @@ +package apicrypt + +import "PaymentCenter/app/models/appmodel" + +func NewRsa(app *appmodel.App) ApiDecrypt { + return &Rsa{ + App: app, + } +} + +func (r *Rsa) Encrypt(decryptData interface{}) (encryptData string, err error) { + return +} + +func (r *Rsa) Decrypt(encryptData string) (decryptData map[string]interface{}, err error) { + return +} diff --git a/app/services/apicrypt/sm2.go b/app/services/apicrypt/sm2.go new file mode 100644 index 0000000..2a18c77 --- /dev/null +++ b/app/services/apicrypt/sm2.go @@ -0,0 +1,9 @@ +package apicrypt + +func (r *SM2) Encrypt(decryptData interface{}) (encryptData string, err error) { + return +} + +func (r *SM2) Decrypt(encryptData string) (decryptData map[string]interface{}, err error) { + return +} diff --git a/app/services/apicrypt/sm4.go b/app/services/apicrypt/sm4.go new file mode 100644 index 0000000..4e16213 --- /dev/null +++ b/app/services/apicrypt/sm4.go @@ -0,0 +1,9 @@ +package apicrypt + +func (r *SM4) Encrypt(decryptData interface{}) (encryptData string, err error) { + return +} + +func (r *SM4) Decrypt(encryptData string) (decryptData map[string]interface{}, err error) { + return +} diff --git a/app/services/apicrypt/types.go b/app/services/apicrypt/types.go new file mode 100644 index 0000000..2e6e8ec --- /dev/null +++ b/app/services/apicrypt/types.go @@ -0,0 +1,22 @@ +package apicrypt + +import "PaymentCenter/app/models/appmodel" + +type ( + ApiDecrypt interface { + Encrypt(decryptData interface{}) (encryptData string, err error) + Decrypt(encryptData string) (decryptData map[string]interface{}, err error) + } + + Rsa struct { + App *appmodel.App + } + + SM2 struct { + App *appmodel.App + } + + SM4 struct { + App *appmodel.App + } +) diff --git a/app/services/app.go b/app/services/app.go index 90dd740..4c5c4b3 100644 --- a/app/services/app.go +++ b/app/services/app.go @@ -8,6 +8,7 @@ import ( "PaymentCenter/app/models/appmodel" "PaymentCenter/app/models/merchantmodel" "PaymentCenter/app/models/paychannelmodel" + "database/sql" "xorm.io/builder" ) @@ -84,3 +85,20 @@ func AppDelete(req entities.IdRequest) (code int) { code = handErr(err) return } + +func AppFindOne(req entities.IdRequest, col ...string) (row *appmodel.App, code int) { + repo := data.NewAppRepo(paychannelmodel.GetInstance().GetDb()) + + // 拼接查询条件 + conn := builder.NewCond() + conn = conn.And(builder.Eq{"Id": req.Id}) + m := appmodel.App{Id: req.Id} + row, err := repo.AppFindOne(&m, conn, col...) + if err != nil { + if err == sql.ErrNoRows { + return nil, errorcode.AppNotFound + } + return row, errorcode.SystemError + } + return row, errorcode.Success +} diff --git a/app/utils/encrypt/rsa/rsa_test.go b/app/utils/encrypt/rsa/rsa_test.go index a8e6e02..5425c75 100644 --- a/app/utils/encrypt/rsa/rsa_test.go +++ b/app/utils/encrypt/rsa/rsa_test.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "fmt" "testing" + "time" ) const ( @@ -13,7 +14,8 @@ const ( ) func TestRsaEncrypt(t *testing.T) { - fmt.Printf("%s\n", encrypt()) + fmt.Println(time.Now().UnixNano() / (1000000)) + //fmt.Printf("%s\n", encrypt()) } func TestRsaDecrypt(t *testing.T) { diff --git a/app/utils/util.go b/app/utils/util.go index 0f49ed1..2674035 100644 --- a/app/utils/util.go +++ b/app/utils/util.go @@ -431,3 +431,12 @@ func SonicApiDataToStruct(data interface{}, structInterFace interface{}) (dataSt err = sonic.Unmarshal(bytes, &structInterFace) return structInterFace, err } + +func ContainsString(slice []string, s string) bool { + for _, item := range slice { + if item == s { + return true + } + } + return false +} diff --git a/config/config.go b/config/config.go index 9fdff6f..5f17b3d 100644 --- a/config/config.go +++ b/config/config.go @@ -22,6 +22,7 @@ type Config struct { Debug bool `toml:"Debug"` PrometheusCollectEnable bool `toml:"PrometheusCollectEnable"` SkyWalkingOapServer string `toml:"SkyWalkingOapServer"` + TimeOut int64 `toml:"TimeOut"` Log config.LogConfig `toml:"Log"` Redis config.RedisConfig `toml:"Redis"` Mns config.MnsConfig `toml:"AliMns"`