diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..496ee2c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/api/common.go b/api/common.go new file mode 100644 index 0000000..834671c --- /dev/null +++ b/api/common.go @@ -0,0 +1,15 @@ +package api + +import ( + "github.com/gin-gonic/gin" + "gold-shop/model" +) + +func user(c *gin.Context) *model.User { + u, exists := c.Get("user") + if !exists { + return nil + } + user := u.(*model.User) + return user +} diff --git a/api/index.go b/api/index.go index 130871d..3b5dcdc 100644 --- a/api/index.go +++ b/api/index.go @@ -1,21 +1,14 @@ package api import ( - "bytes" - "encoding/json" - "fmt" "github.com/gin-gonic/gin" - "github.com/smartwalle/alipay/v3" - "io" - "jypay/errors" - "jypay/global" - "jypay/model" - "jypay/request" - "jypay/utils" - "log" - "net/http" + "gold-shop/errors" + "gold-shop/request" + "gold-shop/service" + "gold-shop/utils" + "gold-shop/utils/payment" + "gold-shop/utils/weixin" "strconv" - "time" ) func Index(c *gin.Context) (utils.Data, error) { @@ -26,192 +19,101 @@ func Error(c *gin.Context) (utils.Data, error) { return nil, errors.NewBusinessError("测试", "1122") } -func Pay(c *gin.Context) (utils.Data, error) { - req := request.OrderRequest{} - err := c.BindJSON(&req) - if err != nil { - fmt.Printf("bind json err:%v", err) - return nil, errors.NewBusinessError("参数错误") - } - - order, err := saveOrder(req) - if err != nil { - return nil, err - } - - var param = alipay.TradeWapPay{} - param.OutTradeNo = order.OrderNo - param.TotalAmount = strconv.FormatFloat(order.PayAmount, 'f', -1, 64) - param.Subject = order.Subject - token := utils.Md5(order.OrderNo + strconv.Itoa(order.UserId) + strconv.FormatInt(time.Now().Unix(), 10)) - param.NotifyURL = global.Config.Server.Domain + "/notify" - param.ReturnURL = global.Config.Server.Domain + "/return?token=" + token - client, err := alipay.New(global.Config.Alipay.AppId, global.Config.Alipay.PrivateKey, true) - if err != nil { - return nil, errors.NewBusinessError("初始化支付宝失败") - } - result, err := client.TradeWapPay(param) - if err != nil { - return nil, errors.NewBusinessError("请求支付宝失败:" + err.Error()) - } +func Register(c *gin.Context) (utils.Data, error) { + mobile := c.PostForm("mobile") + password := c.PostForm("password") + err := service.UserService.Register(mobile, password) + return nil, err +} - fmt.Println(result.String()) - order.PayUrl = result.String() - order.Token = token - global.DB.Save(&order) +func Login(c *gin.Context) (utils.Data, error) { + mobile := c.PostForm("mobile") + password := c.PostForm("password") + token, err := service.UserService.Login(mobile, password) + return utils.Data{"token": token}, err +} - data := utils.Data{ - "pay_url": global.Config.Server.Domain + "/payment?token=" + token, - } +func GetUserInfo(c *gin.Context) (utils.Data, error) { + user, _ := c.Get("user") + data := utils.Data{"user": user} return data, nil } -func saveOrder(req request.OrderRequest) (*model.Order, error) { - if req.OrderNo == "" { - return nil, errors.NewBusinessError("订单号[orderNo]不能为空") - } - - order := model.Order{} - global.DB.Where("order_no = ?", req.OrderNo).First(&order) - - order.OrderNo = req.OrderNo - order.UserId = req.UserId - order.UserAccount = req.UserAccount - order.GameId = req.GameId - order.GameName = req.GameName - order.ServerId = req.ServerId - order.ServerName = req.ServerName - order.Subject = req.Subject - order.RoleId = req.RoleId - order.RoleName = req.RoleName - order.PayAmount = float64(req.PayAmount) / 100 - order.NotifyUrl = req.NotifyUrl - order.ReturnUrl = req.ReturnUrl - order.PromoteId = req.PromoteId - order.PromoteAccount = req.PromoteAccount - order.PayStatus = 0 - - result := global.DB.Create(&order) - if result.Error != nil { - return nil, errors.NewBusinessError("数据异常") - } - - return &order, nil +func ModifyPassword(c *gin.Context) (utils.Data, error) { + oldPassword := c.PostForm("oldPassword") + password := c.PostForm("password") + err := service.UserService.ModifyPassword(password, oldPassword, user(c)) + return nil, err } -func Notify(c *gin.Context) { - err := c.Request.ParseForm() - if err != nil { - log.Printf("参数错误:%v", err) - return - } - client, err := alipay.New(global.Config.Alipay.AppId, global.Config.Alipay.PrivateKey, true) +func GetProductInfo(c *gin.Context) (utils.Data, error) { + productId := c.PostForm("productId") + id, _ := strconv.Atoi(productId) + product, err := service.ProductService.GetProductInfo(id) if err != nil { - log.Printf("初始化支付宝失败:%v", err) - return + return nil, err } + data := utils.Data{"product": product} + return data, nil +} - client.LoadAliPayPublicKey(global.Config.Alipay.AliPublicKey) - - notification, err := client.DecodeNotification(c.Request.Form) +func Payment(c *gin.Context) (utils.Data, error) { + var paymentRequest request.PaymentRequest + err := c.ShouldBind(&paymentRequest) if err != nil { - log.Printf("解析异步通知发生错误:%v", err) - return + return nil, errors.NewBusinessError("参数错误") } - order := model.Order{} - tx := global.DB.Where("order_no = ?", notification.OutTradeNo).First(&order) - if tx.Error != nil { - log.Printf("订单不存在:%s", notification.OutTradeNo) - return + param := payment.WxPayParam{} + param.Remark = "payment" + param.OrderId = utils.GenerateNo("payment") + param.OpenId = paymentRequest.OpenID + param.Amount = paymentRequest.Amount + param.NotifyUrl = "" + result, err := payment.PayApi.WxPay(param) + if err != nil { + return nil, err } - now := time.Now() - if notification.TradeStatus == "TRADE_SUCCESS" || notification.TradeStatus == "TRADE_FINISHED" { - order.PayStatus = 1 - order.PayTime = &now - tx := global.DB.Save(order) - if tx.Error != nil { - log.Printf("更新订单失败:%s", notification.OutTradeNo) - return - } + if result.Status != payment.Success { + return nil, errors.NewBusinessError(result.Message) } - notifyData := make(map[string]interface{}) - notifyData["trade_no"] = notification.TradeNo - notifyData["out_trade_no"] = notification.OutTradeNo - notifyData["trade_status"] = notification.TradeStatus - notifyData["total_amount"] = notification.TotalAmount - notifyResult := postToSdk(order.NotifyUrl, notifyData) - if notifyResult == "success" { - client.ACKNotification(c.Writer) + data := utils.Data{ + "paySign": result.PaySign, + "package": result.Package, + "signType": result.PaySignType, + "nonceStr": result.NonceStr, + "appId": result.AppId, + "timeStamp": result.Timestamp, } + return data, nil } -func TestPost(c *gin.Context) (utils.Data, error) { - notifyData := make(map[string]interface{}) - notifyData["trade_no"] = "112233" - notifyData["out_trade_no"] = "2222222" - notifyData["trade_status"] = "1" - notifyData["total_amount"] = "11.11" - notifyResult := postToSdk("https://api.jianghuifa.cn/callback.php/Notify/kd_callback", notifyData) - return utils.Data{"hello": notifyResult}, nil -} - -func postToSdk(url string, data map[string]interface{}) string { - content, err := json.Marshal(data) +func Order(c *gin.Context) (utils.Data, error) { + var orderRequest request.OrderRequest + err := c.ShouldBind(&orderRequest) if err != nil { - log.Fatalf("无法编码JSON数据:%v", err) - return "fail" - } - - client := &http.Client{} - - req, err := http.NewRequest("POST", url, bytes.NewBuffer(content)) - if err != nil { - log.Fatalf("无法创建新的请求:%v", err) - return "fail" - } - - req.Header.Set("Content-Type", "application/json") - - resp, err := client.Do(req) - if err != nil { - log.Fatalf("无法发送POST请求:%v", err) - return "fail" + return nil, errors.NewBusinessError("参数错误") } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) + order, err := service.OrderService.Order(orderRequest, user(c)) if err != nil { - log.Fatalf("无法读取响应体内容:%v", err) - return "fail" + return nil, err } - - return string(body) + data := utils.Data{"orderNo": order.OrderNo} + return data, nil } -func Return(c *gin.Context) { - token := c.Query("token") - order := model.Order{} - tx := global.DB.Where("token = ?", token).First(&order) - if tx.Error != nil { - c.Writer.WriteHeader(http.StatusOK) - c.Writer.Write([]byte("订单不存在")) - return - } - - c.Redirect(http.StatusMovedPermanently, order.ReturnUrl) +func GetWxAuthUrl(c *gin.Context) (utils.Data, error) { + authUrl := weixin.WxApi.GetAuthUrl("") + data := utils.Data{"url": authUrl} + return data, nil } -func Payment(c *gin.Context) { - token := c.Query("token") - order := model.Order{} - tx := global.DB.Where("token = ?", token).First(&order) - fmt.Println(tx) - if tx.Error != nil { - fmt.Println(tx.Error) - c.Writer.WriteHeader(http.StatusOK) - c.Writer.Write([]byte("订单不存在")) - return +func GetWxOpenId(c *gin.Context) (utils.Data, error) { + code := c.Query("code") + result, err := weixin.WxApi.GetAccessToken(code) + if err != nil { + return nil, err } - - c.Redirect(http.StatusMovedPermanently, order.PayUrl) + data := utils.Data{"openid": result.Openid} + return data, nil } diff --git a/config.yaml b/config.yaml index 72ff652..d0f7b22 100644 --- a/config.yaml +++ b/config.yaml @@ -6,8 +6,23 @@ alipay: private-key: "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQChC/5Psy+biyzdT/CkCknQKax44Ol0i6kAWVkw4BYERevISFqOHpVmlztcnYGx3LIDOeReYQ0ghLLT+6oGrymXzPbIOE+PTUEpPfIRdB8P96mkcbuZ7MnMCsA1vXSjYezVIAu8vdzp4FL2H1p3+gwhuLGT5w9tOUZmNAkKI8xEQwXeFDWlQ5G9w5unigEGnlODqxcStrvL14pceqsA3bm9sEDuSqVAmBXbEZxZyWnYoRJj4kNMqYIXLXwsPzE8268B+0NT9plzv8mGBI2jkwBTXvc1TjnAIK6O0vRfAz82Jz6RhMwIIOrA65F1oO44bihd/4lH+FjrMy5nYeEuBZeZAgMBAAECggEBAJ/EPi7jHL+6em+z9o9GhaO1NB1XQ0MTqj1mZk1OgYkLtLWk0fFb9eso7QMcXqYMw6zfqebXcSZpft8+M5cd/q1R8SEAfC01/wbjJVqbUJWOpQU2r14swqVhpP2rTiMn6sQkXoCH+rkqiiMRR7buoUpy5/hKqcs5ntWVmcItcV/lZ/SOshXIY1Pff9WcJkNUQqtM8OizjSA1htc3XencsOroU6KKLnVdBcGYQJQtr7hBQshgGiaNKapv6n/qGV6J6V7uBuSfwZhNXo0GxbBqZHW3LCesipPkNAvYCu+DhpqVr+j44apGhZ56cIhqdYCrnPrMKysvYHnQ7sm3GhwnimECgYEA5WeTVLkRj7gmcWQQn7KobUxfdQXZguJdVYguTwbWENbZRTDxlv3aZvivAMDx9xDfEd58/xqm5mUathxG8M/HINJ9u32elhFLXLHPD5QzCqv4+X+dZmtnnqEHa5smSEpFL2vJ7v8FGnrAqXiZVye7uqcT7j/6hCZol+EZ1SPz6g8CgYEAs7emjtDwKyzyO1kRQfTB/smlS/hfIvknZZKQoYYRgiB60f2t6aDJOzjUMCIgClWpQztDzbKonKx1ykCmiSgtUJF9MVP4iz5cJKc0wdnjO20DxFJGMHl89ejlfrfmM5D1E0d2l7kpO6M/66mjNT7fGtAdorAw8OzKbZh/KCfsq9cCgYEApWEL95ILtP5eyHQI//f+L/1U+7oh2pdyDc1FBTe6bx1UOOtV3zJWltFE6Fgwl5qUFf+9QPNnysSsgwjTo5tGxMS6W8Xt4+XH3KVazrJaMaFUthln0YQwiU0xWkPZT1grlEoyo5c5iKNh7UrB0PEWBzOXzLRW15oQ4R0oUF3A48UCgYARV4Nm/JpwUCH/wBR+PNQLdgHRVuI3SbuXfZEfRQSjfebcJJKHnNBOOqmfC2v0E1gF+M4OJ1NF6w5iueJYEdxtjdx6yhONvDLABrJ8kj3vGhHm+9lyDAcW46Zhl/VKvI4pkhfLhD6KVrJwVyo8lRiKSdLSRBY06WSPNsvuYAvieQKBgQDk52HC2XLdui/wMnESIJ/+qwuKh/BAC7e/jEuZpQxRFVbE8L2m638f+tkXdHlMERqaROd2h31cPpvZzOyeJBvhUEmuQcBfq+G4YsRQIH0XDvx/nBO4m03nFOXyLkFx4X1fZs/0i3CO506WHdgkM5wd8nA6+9S4DdNAjHvoC4WQ3A==" ali-public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhgLRPY+3aSGRvlcivmcPnSSL9v3BXSea3uDOZpIpzydHxQ16c/A2m6kVh9LxlJJngXldOkO2Q4VS32RufZntc9fkjiiuUxDBlFPKl5x72eiQVoBX4yM7j0gtBlwQFezsIPD0SRC/uxj75+MtjDUupAQLA4gB4zgSDmWWYAIGQlgXXAQExr5k7P1dXrXJMP9SpIYn3Uaug5ifqxanoiDCmMp/sMFasjlVBDIpLOZuKgBwcX3d2FmhRdWIWR5UVy3IbtWuqTJ8vqH8j6Y2jVFLxBA7+woYc0s7npZ0kTa0yGXFw/9LGinSGshGUCBjuAoi67cW6YvODjYFHuGqsrXZvwIDAQAB" database: - host: "47.98.244.18" + host: "124.223.222.61" port: "3306" - username: "liaojinling" - password: "Ljl@3115316" - dbname: "juyou" \ No newline at end of file + username: "elf1990" + password: "XtN1YiaqP4BxC9MEe" + dbname: "gold-shop" +redis: + host: "127.0.0.1" + port: "6379" + password: "" + db: 0 +payment: + base-url: "http://api2.lfwin.com" + api-key: "00014005" + sign-key: "punr8ucu" + wx-pay: + sub-app-id: "wxb1bec7d809e7cf40" + sub-app-secret: "" +jwt: + key: "I2js2oElEo82NmRru8v73Nwm" + issuer: "gold-shop" \ No newline at end of file diff --git a/config/config.go b/config/config.go index 2be0245..2ad81c2 100644 --- a/config/config.go +++ b/config/config.go @@ -4,4 +4,7 @@ type Config struct { Server Server Database Database Alipay Alipay + Jwt Jwt + Redis Redis + Payment Payment } diff --git a/config/jwt.go b/config/jwt.go new file mode 100644 index 0000000..0caca7b --- /dev/null +++ b/config/jwt.go @@ -0,0 +1,6 @@ +package config + +type Jwt struct { + Issuer string + Key string +} diff --git a/config/payment.go b/config/payment.go new file mode 100644 index 0000000..12a96c3 --- /dev/null +++ b/config/payment.go @@ -0,0 +1,13 @@ +package config + +type Payment struct { + BaseUrl string + AppKey string + SignKey string + WxPay WxPay +} + +type WxPay struct { + SubAppId string + SubAppSecret string +} diff --git a/config/redis.go b/config/redis.go new file mode 100644 index 0000000..9123088 --- /dev/null +++ b/config/redis.go @@ -0,0 +1,8 @@ +package config + +type Redis struct { + Host string + Port string + Password string + DB int +} diff --git a/global/global.go b/global/global.go index 801349b..52aee07 100644 --- a/global/global.go +++ b/global/global.go @@ -1,9 +1,11 @@ package global import ( + "github.com/redis/go-redis/v9" + "gold-shop/config" "gorm.io/gorm" - "jypay/config" ) var Config *config.Config var DB *gorm.DB +var Redis *redis.Client diff --git a/go.mod b/go.mod index d95f1f2..2acb41f 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module jypay +module gold-shop go 1.21.1 @@ -11,34 +11,45 @@ require ( ) require ( - github.com/bytedance/sonic v1.10.2 // indirect + github.com/bytedance/sonic v1.11.3 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gin-contrib/cors v1.7.1 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-pay/bm v0.0.1 // indirect + github.com/go-pay/gopay v1.5.100 // indirect + github.com/go-pay/util v0.0.2 // indirect + github.com/go-pay/xhttp v0.0.2 // indirect + github.com/go-pay/xlog v0.0.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.16.0 // indirect + github.com/go-playground/validator/v10 v10.19.0 // indirect github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.6 // indirect - github.com/leodido/go-urn v1.2.4 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.0 // indirect + github.com/redis/go-redis/v9 v9.5.1 // indirect github.com/smartwalle/ncrypto v1.0.4 // indirect github.com/smartwalle/ngx v1.0.9 // indirect github.com/smartwalle/nsign v1.0.9 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect - golang.org/x/arch v0.6.0 // indirect - golang.org/x/crypto v0.16.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/arch v0.7.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.22.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect ) diff --git a/go.sum b/go.sum index 761ce3d..0177391 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,10 @@ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1 github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= +github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA= +github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= @@ -12,12 +16,28 @@ github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLI github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 h1:6VSn3hB5U5GeA6kQw4TwWIWbOhtvR2hmbBJnTOtqTWc= +github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6/go.mod h1:YxOVT5+yHzKvwhsiSIWmbAYM3Dr9AEEbER2dVayfBkg= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gin-contrib/cors v1.7.1 h1:s9SIppU/rk8enVvkzwiC2VK3UZ/0NNGsWfUKvV55rqs= +github.com/gin-contrib/cors v1.7.1/go.mod h1:n/Zj7B4xyrgk/cX1WCX2dkzFfaNm/xJb6oIUk7WTtps= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-pay/bm v0.0.1 h1:F2d1KhrupJr7yGPCQTVeYjeOJwN35WhoofopSm6undY= +github.com/go-pay/bm v0.0.1/go.mod h1:/6bIb0yBj8JbATmE+ib41me4RikMGN3f/XSDF5FjsPQ= +github.com/go-pay/gopay v1.5.100 h1:jFpyLA/flrSigY0WFpNaSuQcMFn0yjFpObBnlTzqO9Y= +github.com/go-pay/gopay v1.5.100/go.mod h1:3z9xfh7w3x5rJzH9qFb3oxPOeaBrFP4kB3LNVXbziHM= +github.com/go-pay/util v0.0.2 h1:goJ4f6kNY5zzdtg1Cj8oWC+Cw7bfg/qq2rJangMAb9U= +github.com/go-pay/util v0.0.2/go.mod h1:qM8VbyF1n7YAPZBSJONSPMPsPedhUTktewUAdf1AjPg= +github.com/go-pay/xhttp v0.0.2 h1:O8rnd/d03WsboFtUthwFMg61ikHRfYHyD1m0JiUx60g= +github.com/go-pay/xhttp v0.0.2/go.mod h1:BnuvXpLKkXTFMOBc5MTb0hxdrstwunbzQPJUZOsNbt4= +github.com/go-pay/xlog v0.0.2 h1:kUg5X8/5VZAPDg1J5eGjA3MG0/H5kK6Ew0dW/Bycsws= +github.com/go-pay/xlog v0.0.2/go.mod h1:DbjMADPK4+Sjxj28ekK9goqn4zmyY4hql/zRiab+S9E= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -26,10 +46,14 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= +github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -43,9 +67,13 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -55,8 +83,12 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= +github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= +github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/smartwalle/alipay/v3 v3.2.20 h1:IjpG3YYgUgzCfS0z/EHlUbbr0OlrmOBHUst/3FzToYE= github.com/smartwalle/alipay/v3 v3.2.20/go.mod h1:KWg91KsY+eIOf26ZfZeH7bed1bWulGpGrL1ErHF3jWo= github.com/smartwalle/ncrypto v1.0.4 h1:P2rqQxDepJwgeO5ShoC+wGcK2wNJDmcdBOWAksuIgx8= @@ -68,6 +100,7 @@ github.com/smartwalle/nsign v1.0.9/go.mod h1:eY6I4CJlyNdVMP+t6z1H6Jpd4m5/V+8xi44 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -76,6 +109,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -83,14 +118,26 @@ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc= golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= +golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= @@ -98,8 +145,11 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/initialize/initialize.go b/initialize/initialize.go index 1ccb078..5eda4b5 100644 --- a/initialize/initialize.go +++ b/initialize/initialize.go @@ -2,10 +2,11 @@ package initialize import ( "fmt" + "github.com/redis/go-redis/v9" + "gold-shop/config" "gopkg.in/yaml.v3" "gorm.io/driver/mysql" "gorm.io/gorm" - "jypay/config" "os" ) @@ -33,3 +34,11 @@ func InitDB(conf *config.Config) *gorm.DB { } return db } + +func InitRedis(conf *config.Config) *redis.Client { + return redis.NewClient(&redis.Options{ + Addr: conf.Redis.Host + ":" + conf.Redis.Port, + Password: conf.Redis.Password, // no password set + DB: conf.Redis.DB, // use default DB + }) +} diff --git a/main.go b/main.go index d2b0ed0..00b9699 100644 --- a/main.go +++ b/main.go @@ -1,26 +1,113 @@ package main import ( + "encoding/json" "fmt" + "github.com/fvbock/endless" "github.com/gin-gonic/gin" - "jypay/api" - "jypay/global" - "jypay/initialize" - "jypay/utils" + "gold-shop/global" + "gold-shop/initialize" + "gold-shop/request" + "gold-shop/route" + "gold-shop/utils" + "net/http" + "net/url" + "time" ) func main() { + payOrderCommon() +} + +func RunServer() { global.Config = initialize.InitConfig() global.DB = initialize.InitDB(global.Config) - fmt.Println(global.Config) + global.Redis = initialize.InitRedis(global.Config) + r := gin.Default() - r.GET("/ping", utils.BuildJsonHandler(api.Index)) - r.GET("/error", utils.BuildJsonHandler(api.Error)) - r.POST("/pay", utils.BuildJsonHandler(api.Pay)) - r.GET("/payment", utils.BuildHandler(api.Payment)) - r.POST("/notify", utils.BuildHandler(api.Notify)) - r.GET("/return", utils.BuildHandler(api.Return)) - r.GET("/test-post", utils.BuildJsonHandler(api.TestPost)) - err := r.Run(":" + global.Config.Server.Port) // listen and serve on 0.0.0.0:8080 - panic(err) + s := &http.Server{ + Addr: ":8080", + Handler: r, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + MaxHeaderBytes: 1 << 20, + } + route.Initial(r) + err := endless.ListenAndServe(":"+global.Config.Server.Port, s.Handler) + if err != nil { + panic(err) + } +} + +func payOrder1() { + params := url.Values{} + params.Set("service", "pay.order") + params.Set("apikey", "00014005") + params.Set("money", "0.01") + params.Set("nonce_str", "slfksldfs22dfsf") + //params.Set("sign", "") + params.Set("auth_token", "555555") + //params.Set("mch_orderid", "") + //params.Set("mid", "") + //params.Set("guid", "") + params.Set("remarks", "tst") + sign := utils.Sign(params, "punr8ucu") + params.Set("sign", sign) + fmt.Println(params.Encode()) + utils.Post("http://api2uat.lfwin.com/payapi/cash/pay_order", params) +} + +func payOrderCommon() { + params := url.Values{} + params.Set("service", "comm.js.pay") + params.Set("apikey", "00014005") + params.Set("money", "0.01") + params.Set("sub_appid", "wxb1bec7d809e7cf40") + params.Set("sub_openid", "ohyVV0v4UBc63GL8D8nlEL0UO5vE") + params.Set("nonce_str", "slfksldfs22dfsf") + //params.Set("sign", "") + params.Set("mch_orderid", "444444444") + //params.Set("mch_orderid", "") + //params.Set("notify_url", "") + //params.Set("guid", "") + params.Set("remarks", "tst") + sign := utils.Sign(params, "punr8ucu") + params.Set("sign", sign) + fmt.Println(params.Encode()) + utils.Post("http://api2.lfwin.com/payapi/mini/wxpay", params) +} + +func payOrder2() { + params := url.Values{} + params.Set("grant_type", "client_credentials") + utils.Post1("https://api.paypal.com/v1/oauth2/token", params) +} + +func payOrder3() { + amount := request.Amount{ + CurrencyCode: "USD", + Value: "0.01", + } + purchaseUnit := request.PurchaseUnit{ + Amount: amount, + Description: "test", + CustomId: 1, + } + r := request.CheckOutOrderRequest{ + Intent: "CAPTURE", + PurchaseUnits: []request.PurchaseUnit{ + purchaseUnit, + }, + ApplicationContext: request.ApplicationContext{ + CancelUrl: "https://www.baidu.com", + ReturnUrl: "https://www.baidu.com", + }, + } + body, err := json.Marshal(r) + if err != nil { + panic(err) + } + token := "A21AAPb6qISsbMc4lPtdW4imLL13_m0zH1n8CQ_zL-PQgwvaj1g6tM86GqBBAy1NL55KKDTbbuyMDplzDsk8-rCWzNKPxB2-w" + fmt.Println(string(body)) + utils.Post2("https://api.paypal.com/v2/checkout/orders", string(body), token) } diff --git a/middleware/jwt_middleware.go b/middleware/jwt_middleware.go new file mode 100644 index 0000000..aa12c06 --- /dev/null +++ b/middleware/jwt_middleware.go @@ -0,0 +1,45 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "gold-shop/service" + "gold-shop/utils" + "net/http" + "time" +) + +func JwtMiddleware() gin.HandlerFunc { + return func(c *gin.Context) { + token := c.Request.Header.Get("Authorization") + result := utils.Result{} + if token == "" { + result.Code = utils.Error + result.Message = "TOKEN过期" + c.JSON(http.StatusOK, result) + c.Abort() + return + } + + claims, isValid := utils.CheckToken(token) + if !isValid { + result.Code = utils.ErrorTokenWrong + result.Message = "TOKEN验证失败" + c.JSON(http.StatusOK, result) + c.Abort() + return + } + + // 判断token是否过期 + if time.Now().Unix() > claims.ExpiresAt.Unix() { + result.Code = utils.ErrorTokenExpired + result.Message = "TOKEN过期" + c.JSON(http.StatusOK, result) + c.Abort() + return + } + + user := service.UserService.GetUserInfo(claims.Identity) + c.Set("user", user) + c.Next() + } +} diff --git a/middleware/test_middleware.go b/middleware/test_middleware.go new file mode 100644 index 0000000..7ab4cbc --- /dev/null +++ b/middleware/test_middleware.go @@ -0,0 +1,17 @@ +package middleware + +import ( + "fmt" + "github.com/gin-gonic/gin" +) + +func TestMiddleware(c *gin.Context) { + // 在请求处理之前执行的逻辑 + fmt.Println("Start Logging") + + // 将请求传递给下一个处理程序 + c.Next() + + // 在请求处理之后执行的逻辑 + fmt.Println("End Logging") +} diff --git a/model/order.go b/model/order.go index c6b1005..7f2dbbc 100644 --- a/model/order.go +++ b/model/order.go @@ -5,30 +5,14 @@ import ( ) type Order struct { - ID uint - OrderNo string - UserId int - UserAccount string - RoleName string - RoleId string - GameId int - GameName string - ServerId string - ServerName string - PayAmount float64 - PayStatus int8 - PayUrl string - NotifyUrl string - ReturnUrl string - Subject string - Token string - PromoteId int - PromoteAccount string - PayTime *time.Time - CreatedAt time.Time - UpdatedAt time.Time + ID uint + OrderNo string + UserID int + Amount float64 + CreatedAt time.Time + UpdatedAt time.Time } func (Order) TableName() string { - return "outer_orders" + return "orders" } diff --git a/model/order_product..go b/model/order_product..go new file mode 100644 index 0000000..611a99e --- /dev/null +++ b/model/order_product..go @@ -0,0 +1,19 @@ +package model + +import "time" + +type OrderProduct struct { + ID uint + OrderNo string + UserID int + ProductID int + Num int + Price float64 + Amount float64 + CreatedAt time.Time + UpdatedAt time.Time +} + +func (OrderProduct) TableName() string { + return "order_products" +} diff --git a/model/product.go b/model/product.go new file mode 100644 index 0000000..2e58355 --- /dev/null +++ b/model/product.go @@ -0,0 +1,16 @@ +package model + +import "time" + +type Product struct { + ID int + Name string + Price float64 + Description string + CreatedAt time.Time + UpdatedAt time.Time +} + +func (Product) TableName() string { + return "products" +} diff --git a/model/user.go b/model/user.go new file mode 100644 index 0000000..088d68b --- /dev/null +++ b/model/user.go @@ -0,0 +1,36 @@ +package model + +import ( + "encoding/json" + "time" +) + +type User struct { + ID int + Mobile string + Nickname string + UserType int `json:"-"` + MasterUserId int `json:"-"` + PasswordHash string `json:"-"` + PaymentPasswordHash string `json:"-"` + Profit float64 + Balance float64 + Status int + CreatedAt time.Time + UpdatedAt time.Time `json:"-"` +} + +func (User) TableName() string { + return "users" +} + +func (u User) MarshalJSON() ([]byte, error) { + type Alias User + return json.Marshal(&struct { + CreatedAt string + *Alias + }{ + CreatedAt: u.CreatedAt.Format("2006-01-02 15:04:05"), + Alias: (*Alias)(&u), + }) +} diff --git a/request/check_out_order_request.go b/request/check_out_order_request.go new file mode 100644 index 0000000..8da30aa --- /dev/null +++ b/request/check_out_order_request.go @@ -0,0 +1,23 @@ +package request + +type CheckOutOrderRequest struct { + Intent string `json:"intent"` + PurchaseUnits []PurchaseUnit `json:"purchase_units"` + ApplicationContext ApplicationContext `json:"application_context"` +} + +type PurchaseUnit struct { + Amount Amount `json:"amount"` + Description string `json:"description"` + CustomId int `json:"custom_id"` +} + +type Amount struct { + CurrencyCode string `json:"currency_code"` + Value string `json:"value"` +} + +type ApplicationContext struct { + CancelUrl string `json:"cancel_url"` + ReturnUrl string `json:"return_url"` +} diff --git a/request/order_request.go b/request/order_request.go index e0ac450..6a65763 100644 --- a/request/order_request.go +++ b/request/order_request.go @@ -1,19 +1,6 @@ package request type OrderRequest struct { - OrderNo string `json:"order_no"` - UserId int `json:"user_id"` - UserAccount string `json:"user_account"` - GameId int `json:"game_id"` - GameName string `json:"game_name"` - ServerId string `json:"server_id"` - ServerName string `json:"server_name"` - Subject string `json:"subject"` - RoleId string `json:"role_id"` - RoleName string `json:"role_name"` - PayAmount int `json:"pay_amount"` - NotifyUrl string `json:"notify_url"` - ReturnUrl string `json:"return_url"` - PromoteId int `json:"promote_id"` - PromoteAccount string `json:"promote_account"` + ProductID int `json:"productId" form:"productId"` + Num int `json:"num" form:"num"` } diff --git a/request/payment_request.go b/request/payment_request.go index b9af2d2..940db03 100644 --- a/request/payment_request.go +++ b/request/payment_request.go @@ -1,5 +1,7 @@ package request type PaymentRequest struct { - Token string `url:"token"` + OpenID string `json:"openId" form:"openId"` + Amount float64 `json:"amount" form:"amount"` + PayType string `json:"payType" form:"payType"` } diff --git a/route/common.go b/route/common.go new file mode 100644 index 0000000..e825e66 --- /dev/null +++ b/route/common.go @@ -0,0 +1,7 @@ +package route + +import "github.com/gin-gonic/gin" + +func Initial(r *gin.Engine) { + h5RouteInit(r) +} diff --git a/route/h5.go b/route/h5.go new file mode 100644 index 0000000..24f1ea7 --- /dev/null +++ b/route/h5.go @@ -0,0 +1,31 @@ +package route + +import ( + "github.com/gin-contrib/cors" + "github.com/gin-gonic/gin" + "gold-shop/api" + "gold-shop/middleware" + "gold-shop/utils" +) + +func h5RouteInit(r *gin.Engine) { + r.Use(cors.Default()) + h5Group := r.Group("/h5") + h5Group.Use(cors.Default()) + h5Group.POST("/login", utils.JsonHandler(api.Login)) + h5Group.POST("/register", utils.JsonHandler(api.Register)) + h5Group.GET("/get-product-info", utils.JsonHandler(api.GetProductInfo)) + + authGroup := h5Group.Group("") + authGroup.Use(middleware.JwtMiddleware()) + { + authGroup.GET("/ping", utils.JsonHandler(api.Index)) + authGroup.GET("/error", utils.JsonHandler(api.Error)) + authGroup.GET("/get-user-info", utils.JsonHandler(api.GetUserInfo)) + authGroup.GET("/order", utils.JsonHandler(api.Order)) + authGroup.GET("/modify-password", utils.JsonHandler(api.ModifyPassword)) + authGroup.GET("/payment", utils.JsonHandler(api.Payment)) + authGroup.GET("/get-wx-open-id", utils.JsonHandler(api.GetWxOpenId)) + authGroup.GET("/get-wx-auth-url", utils.JsonHandler(api.GetWxAuthUrl)) + } +} diff --git a/service/order_service.go b/service/order_service.go new file mode 100644 index 0000000..4d00320 --- /dev/null +++ b/service/order_service.go @@ -0,0 +1,58 @@ +package service + +import ( + e "errors" + "gold-shop/errors" + "gold-shop/global" + "gold-shop/model" + "gold-shop/request" + "gold-shop/utils" + "gorm.io/gorm" +) + +var OrderService = orderService{} + +type orderService struct { +} + +func (orderService) Order(orderRequest request.OrderRequest, user *model.User) (*model.Order, error) { + product := &model.Product{} + err := global.DB.Where("product_id", orderRequest.ProductID).First(product).Error + if e.Is(err, gorm.ErrRecordNotFound) { + return nil, errors.NewBusinessError("商品不存在") + } + totalAmount := float64(orderRequest.Num) * product.Price + if user.Balance < totalAmount { + return nil, errors.NewBusinessError("账号余额不足") + } + + orderNo := utils.GenerateNo("order") + + tx := global.DB.Begin() + order := model.Order{} + order.OrderNo = orderNo + order.Amount = totalAmount + order.UserID = user.ID + err = global.DB.Save(&order).Error + if err != nil { + tx.Rollback() + return nil, errors.NewBusinessError("保存数据失败") + } + + orderProduct := model.OrderProduct{} + orderProduct.ProductID = orderRequest.ProductID + orderProduct.OrderNo = orderNo + orderProduct.Price = product.Price + orderProduct.Amount = totalAmount + orderProduct.Num = orderRequest.Num + err = global.DB.Save(&orderProduct).Error + if err != nil { + tx.Rollback() + return nil, errors.NewBusinessError("保存数据失败") + } + + global.DB.Model(user).Update("balance", gorm.Expr("balance - ?", totalAmount)) + tx.Commit() + + return &order, nil +} diff --git a/service/product_service.go b/service/product_service.go new file mode 100644 index 0000000..6fa4c69 --- /dev/null +++ b/service/product_service.go @@ -0,0 +1,23 @@ +package service + +import ( + e "errors" + "gold-shop/errors" + "gold-shop/global" + "gold-shop/model" + "gorm.io/gorm" +) + +var ProductService = productService{} + +type productService struct { +} + +func (productService) GetProductInfo(productID int) (*model.Product, error) { + product := &model.Product{} + err := global.DB.Where("product_id", productID).First(product).Error + if e.Is(err, gorm.ErrRecordNotFound) { + return nil, errors.NewBusinessError("商品不存在") + } + return product, nil +} diff --git a/service/user_service.go b/service/user_service.go new file mode 100644 index 0000000..592b976 --- /dev/null +++ b/service/user_service.go @@ -0,0 +1,53 @@ +package service + +import ( + e "errors" + "gold-shop/errors" + "gold-shop/global" + "gold-shop/model" + "gold-shop/utils" + "gorm.io/gorm" +) + +var UserService = userService{} + +type userService struct { +} + +func (userService) Login(mobile string, password string) (string, error) { + user := &model.User{} + err := global.DB.Where("mobile", mobile).First(user).Error + if e.Is(err, gorm.ErrRecordNotFound) { + return "", errors.NewBusinessError("手机号或密码错误") + } + if utils.PasswordVerify(password, user.PasswordHash) { + return utils.GenerateToken(user.ID, "user") + } + return "", errors.NewBusinessError("手机号或密码错误") +} + +func (userService) Register(mobile string, password string) error { + user := &model.User{} + err := global.DB.Where("mobile", mobile).First(user).Error + if err == nil { + return errors.NewBusinessError("手机号已注册") + } + user.Mobile = mobile + passwordHash, _ := utils.PasswordHash(password) + user.PasswordHash = passwordHash + return global.DB.Save(user).Error +} + +func (userService) GetUserInfo(userId int) *model.User { + user := &model.User{} + global.DB.Where("id", userId).First(user) + return user +} +func (userService) ModifyPassword(password string, oldPassword string, user *model.User) error { + if !utils.PasswordVerify(oldPassword, user.PasswordHash) { + return errors.NewBusinessError("旧密码错误") + } + passwordHash, _ := utils.PasswordHash(password) + user.PasswordHash = passwordHash + return global.DB.Save(user).Error +} diff --git a/shop.sql b/shop.sql new file mode 100644 index 0000000..bf002f2 --- /dev/null +++ b/shop.sql @@ -0,0 +1,92 @@ +CREATE TABLE `banners` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', + `img_url` varchar(400) DEFAULT NULL COMMENT 'banner图url', + `title` varchar(64) DEFAULT NULL COMMENT '标题', + `type` varchar(32) DEFAULT NULL COMMENT '栏目类型', + `link_url` varchar(255) DEFAULT NULL COMMENT '点击banner跳转到url', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `sort` int DEFAULT NULL COMMENT '显示顺序', + `status` tinyint(1) not null default '0' COMMENT 'banner状态(0启用 1禁用)', + `created_at` timestamp not null default current_timestamp COMMENT '创建时间', + `updated_at` timestamp not null default current_timestamp COMMENT '最后更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='banner'; + +CREATE TABLE `users` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', + `mobile` varchar(20) not NULL COMMENT '手机号', + `nickname` varchar(32) not NULL default '' COMMENT '昵称', + `user_type` tinyint(1) not null default 1 COMMENT '账号类型:1-主账号/2-子账号', + `master_user_id` varchar(32) not null default 0 COMMENT '主账号ID', + `password_hash` varchar(64) not NULL COMMENT '登录密码', + `payment_password_hash` varchar(64) not NULL default '' COMMENT '支付密码', + `balance` decimal(10,2) not null default '0.00' COMMENT '账号余额', + `profit` decimal(10,2) not null default '0.00' COMMENT '收益', + `status` tinyint(1) not null default 1 COMMENT '账号状体(1启用)', + `created_at` timestamp not null default current_timestamp COMMENT '创建时间', + `updated_at` timestamp not null default current_timestamp COMMENT '最后更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; + +CREATE TABLE `user_balances` ( + `user_id` int(11) NOT NULL COMMENT '用户ID', + `created_at` timestamp not null default current_timestamp COMMENT '创建时间', + `updated_at` timestamp not null default current_timestamp COMMENT '最后更新时间', + PRIMARY KEY (`user_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户余额表'; + +CREATE TABLE `payments` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', + `user_id` int(11) NOT NULL COMMENT '用户ID', + `order_no` varchar(32) not NULL default '' COMMENT '订单号', + `amount` tinyint(1) not null default 1 COMMENT '账号类型:1-主账号/2-子账号', + `status` tinyint(1) not null default 1 COMMENT '账号状体(1启用)', + `created_at` timestamp not null default current_timestamp COMMENT '创建时间', + `updated_at` timestamp not null default current_timestamp COMMENT '最后更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表'; + +CREATE TABLE `orders` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', + `user_id` int(11) NOT NULL COMMENT '用户ID', + `order_no` varchar(32) not NULL default '' COMMENT '订单号', + `amount` decimal(10, 2) not null default 1 COMMENT '订单金额', + `status` tinyint(1) not null default 1 COMMENT '账号状体(1启用)', + `created_at` timestamp not null default current_timestamp COMMENT '创建时间', + `updated_at` timestamp not null default current_timestamp COMMENT '最后更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表'; + +CREATE TABLE `order_products` ( + `order_product_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', + `user_id` int(11) NOT NULL COMMENT '用户ID', + `order_no` varchar(32) not NULL default '' COMMENT '订单号', + `product_id` int(11) NOT NULL COMMENT '产品ID', + `num` int(11) NOT NULL COMMENT '商品数量', + `price` decimal(10, 2) not null default 1 COMMENT '商品单价', + `amount` decimal(10, 2) not null default 1 COMMENT '商品总金额', + `created_at` timestamp not null default current_timestamp COMMENT '创建时间', + `updated_at` timestamp not null default current_timestamp COMMENT '最后更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单商品表'; + +CREATE TABLE `products` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', + `name` varchar(255) NOT NULL COMMENT '名称', + `description` text default null COMMENT '描述', + `price` decimal(10, 2) not null default '0.00' COMMENT '价格', + `created_at` timestamp not null default current_timestamp COMMENT '创建时间', + `updated_at` timestamp not null default current_timestamp COMMENT '最后更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表'; + +CREATE TABLE `profits` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', + `date` date NOT NULL COMMENT '日期', + `product_id` int(11) not default COMMENT '产品ID', + `amount` tinyint(1) not null default 1 COMMENT '账号类型:1-主账号/2-子账号', + `status` tinyint(1) not null default 1 COMMENT '账号状体(1启用)', + `created_at` timestamp not null default current_timestamp COMMENT '创建时间', + `updated_at` timestamp not null default current_timestamp COMMENT '最后更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='收益表'; diff --git a/utils/encrypt.go b/utils/encrypt.go index 39a2b5a..e42f2c5 100644 --- a/utils/encrypt.go +++ b/utils/encrypt.go @@ -4,6 +4,7 @@ import ( "crypto/md5" "encoding/hex" "fmt" + "golang.org/x/crypto/bcrypt" "io" "net/http" "net/url" @@ -23,6 +24,16 @@ func Sign(params url.Values, signKey string) string { return Md5(params.Encode() + "&signkey=" + signKey) } +func PasswordHash(password string) (string, error) { + bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + return string(bytes), err +} + +func PasswordVerify(password, hash string) bool { + err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) + return err == nil +} + func Post(url string, params url.Values) { client := &http.Client{} body := strings.NewReader(params.Encode()) diff --git a/utils/jwt.go b/utils/jwt.go new file mode 100644 index 0000000..0316242 --- /dev/null +++ b/utils/jwt.go @@ -0,0 +1,52 @@ +package utils + +import ( + "github.com/golang-jwt/jwt/v5" + "gold-shop/global" + "time" +) + +type MyClaims struct { + Identity int `json:"identity"` + Role string `json:"role"` + jwt.RegisteredClaims +} + +func GenerateToken(identity int, role string) (string, error) { + SetClaims := MyClaims{ + Identity: identity, + Role: role, + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(time.Now().Add(3 * time.Hour)), // 有效时间 + IssuedAt: jwt.NewNumericDate(time.Now()), // 签发时间 + NotBefore: jwt.NewNumericDate(time.Now()), // 生效时间 + Issuer: global.Config.Jwt.Issuer, // 签发人 + Subject: "somebody", // 主题 + ID: "1", // JWT ID用于标识该JWT + Audience: []string{"somebody_else"}, // 用户 + }, + } + + // 使用指定的加密方式和声明类型创建新令牌 + tokenStruct := jwt.NewWithClaims(jwt.SigningMethodHS256, SetClaims) + // 获得完整的、签名的令牌 + token, err := tokenStruct.SignedString([]byte(global.Config.Jwt.Key)) + return token, err +} + +func CheckToken(token string) (*MyClaims, bool) { + //解析、验证并返回token。 + tokenObj, err := jwt.ParseWithClaims(token, &MyClaims{}, func(token *jwt.Token) (interface{}, error) { + return []byte(global.Config.Jwt.Key), nil + }) + + if err != nil { + return nil, false + } + + if claims, ok := tokenObj.Claims.(*MyClaims); ok && tokenObj.Valid { + return claims, true + } else { + return nil, false + } +} diff --git a/utils/payment/const.go b/utils/payment/const.go new file mode 100644 index 0000000..6fd7122 --- /dev/null +++ b/utils/payment/const.go @@ -0,0 +1,3 @@ +package payment + +const Success = "10000" diff --git a/utils/payment/pay_api.go b/utils/payment/pay_api.go new file mode 100644 index 0000000..da7133f --- /dev/null +++ b/utils/payment/pay_api.go @@ -0,0 +1,79 @@ +package payment + +import ( + "encoding/json" + "fmt" + "gold-shop/errors" + "gold-shop/global" + "gold-shop/utils" + "io" + "net/http" + "net/url" + "strings" +) + +var PayApi payApi = payApi{} + +type payApi struct { +} + +func (api *payApi) WxPay(param WxPayParam) (*WxPayResult, error) { + payment := global.Config.Payment + data := url.Values{} + data.Set("service", "comm.js.pay") + data.Set("apikey", payment.AppKey) + data.Set("money", fmt.Sprintf("%.2f", param.Amount)) + data.Set("sub_appid", payment.WxPay.SubAppId) + data.Set("sub_openid", param.OpenId) + data.Set("nonce_str", utils.GenerateRandomString(32)) + data.Set("mch_orderid", param.OrderId) + data.Set("notify_url", param.NotifyUrl) + data.Set("remarks", param.Remark) + sign := api.sign(data, payment.SignKey) + data.Set("sign", sign) + fmt.Println(data.Encode()) + res, err := api.post(payment.BaseUrl+"/payapi/mini/wxpay", data) + if err != nil { + return nil, err + } + result := WxPayResult{} + err = json.Unmarshal(res, &result) + if err != nil { + return nil, errors.NewBusinessError("结果解析错误") + } + return &result, nil +} + +func (payApi) sign(params url.Values, signKey string) string { + fmt.Println(params.Encode() + "&signkey=" + signKey) + return utils.Md5(params.Encode() + "&signkey=" + signKey) +} + +func (payApi) post(url string, data url.Values) ([]byte, error) { + client := &http.Client{} + body := strings.NewReader(data.Encode()) + request, err := http.NewRequest("POST", url, body) + request.Header.Set("content-type", "application/x-www-form-urlencoded") + + if err != nil { + return nil, errors.NewBusinessError("请求错误") + } + response, err := client.Do(request) + + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + + } + }(response.Body) + + bodyBytes, err := io.ReadAll(response.Body) + + fmt.Println(string(bodyBytes)) + + if err != nil { + return nil, errors.NewBusinessError("返回内容错误") + } + + return bodyBytes, nil +} diff --git a/utils/payment/wx_pay_param.go b/utils/payment/wx_pay_param.go new file mode 100644 index 0000000..6bb6358 --- /dev/null +++ b/utils/payment/wx_pay_param.go @@ -0,0 +1,9 @@ +package payment + +type WxPayParam struct { + OpenId string + Amount float64 + OrderId string + NotifyUrl string + Remark string +} diff --git a/utils/payment/wx_pay_result.go b/utils/payment/wx_pay_result.go new file mode 100644 index 0000000..5a508bc --- /dev/null +++ b/utils/payment/wx_pay_result.go @@ -0,0 +1,23 @@ +package payment + +type WxPayResult struct { + AppId string `json:"appId"` + Timestamp string `json:"timeStamp"` + NonceStr string `json:"nonceStr"` + Package string `json:"package"` + PaySign string `json:"paySign"` + PaySignType string `json:"signType"` + Service string `json:"service"` + OrderID string `json:"orderid"` + OrderTime string `json:"order_time"` + MchOrderID string `json:"mch_orderid"` + QrCode string `json:"qr_code"` + TradeType string `json:"trade_type"` + PrepayId string `json:"prepay_id"` + Version string `json:"version"` + Charset string `json:"charset"` + Message string `json:"message"` + Status string `json:"status"` + SignType string `json:"sign_ype"` + Sign string `json:"sign"` +} diff --git a/utils/result.go b/utils/result.go index 47b6285..cf3e804 100644 --- a/utils/result.go +++ b/utils/result.go @@ -3,7 +3,7 @@ package utils import ( syserrors "errors" "github.com/gin-gonic/gin" - "jypay/errors" + "gold-shop/errors" ) type Result struct { @@ -14,7 +14,7 @@ type Result struct { type Data map[string]interface{} -func BuildJsonHandler(api func(c *gin.Context) (Data, error)) func(c *gin.Context) { +func JsonHandler(api func(c *gin.Context) (Data, error)) func(c *gin.Context) { return func(c *gin.Context) { data, err := api(c) result := Result{} @@ -22,7 +22,7 @@ func BuildJsonHandler(api func(c *gin.Context) (Data, error)) func(c *gin.Contex result = buildErrorResult(err) result.Data = data } else { - result.Code = "0000" + result.Code = Success result.Message = "成功" result.Data = data } @@ -30,7 +30,7 @@ func BuildJsonHandler(api func(c *gin.Context) (Data, error)) func(c *gin.Contex } } -func BuildHandler(api func(c *gin.Context)) func(c *gin.Context) { +func Handler(api func(c *gin.Context)) func(c *gin.Context) { return api } @@ -43,7 +43,7 @@ func buildErrorResult(err error) Result { result.Code = businessError.Code result.Message = businessError.Message default: - result.Code = "1000" + result.Code = Error result.Message = "系统异常" } return result diff --git a/utils/result_code.go b/utils/result_code.go new file mode 100644 index 0000000..e150d25 --- /dev/null +++ b/utils/result_code.go @@ -0,0 +1,6 @@ +package utils + +const Success string = "0000" +const Error string = "1000" +const ErrorTokenWrong string = "5000" +const ErrorTokenExpired string = "5001" diff --git a/utils/str.go b/utils/str.go new file mode 100644 index 0000000..516f605 --- /dev/null +++ b/utils/str.go @@ -0,0 +1,31 @@ +package utils + +import ( + "context" + "gold-shop/global" + "math/rand" + "strconv" + "strings" + "time" +) + +func GenerateNo(noType string) string { + now := time.Now() + key := "no_" + noType + ":" + now.Format("200601021504") + cxt := context.Background() + val := global.Redis.Incr(cxt, key).Val() + global.Redis.ExpireAt(cxt, key, now.Add(time.Minute)) + valStr := strconv.Itoa(int(val)) + l := len(valStr) + valStr = strings.Repeat("0", l) + valStr + return now.Format("20060102150405") + valStr +} + +func GenerateRandomString(length int) string { + charSet := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + result := make([]byte, length) + for i := 0; i < length; i++ { + result[i] = charSet[rand.Intn(len(charSet))] + } + return string(result) +} diff --git a/utils/weixin/access_token_result.go b/utils/weixin/access_token_result.go new file mode 100644 index 0000000..b0b77f9 --- /dev/null +++ b/utils/weixin/access_token_result.go @@ -0,0 +1,11 @@ +package weixin + +type AccessTokenResult struct { + AccessToken string `json:"access_token"` + ExpiresIn int `json:"expires_in"` + RefreshToken string `json:"refresh_token"` + Openid string `json:"openid"` + Scope string `json:"scope"` + IsSnapshotuser int `json:"is_snapshotuser"` + Unionid string `json:"unionid"` +} diff --git a/utils/weixin/wx_api.go b/utils/weixin/wx_api.go new file mode 100644 index 0000000..d5b8fdf --- /dev/null +++ b/utils/weixin/wx_api.go @@ -0,0 +1,71 @@ +package weixin + +import ( + "encoding/json" + "fmt" + "gold-shop/errors" + "gold-shop/global" + "io" + "net/http" + "net/url" +) + +var WxApi wxApi = wxApi{} + +type wxApi struct { +} + +func (api wxApi) GetAccessToken(code string) (*AccessTokenResult, error) { + params := url.Values{} + params.Set("appid", global.Config.Payment.WxPay.SubAppId) + params.Set("secret", global.Config.Payment.WxPay.SubAppSecret) + params.Set("code", code) + params.Set("grant_type", "authorization_code") + urlStr := params.Encode() + tokenUrl := "https://api.weixin.qq.com/sns/oauth2/access_token?" + urlStr + body, err := api.get(tokenUrl) + if err != nil { + return nil, err + } + result := AccessTokenResult{} + err = json.Unmarshal(body, &result) + if err != nil { + return nil, errors.NewBusinessError("数据解析错误") + } + return &result, nil +} + +func (api wxApi) GetAuthUrl(redirectUrl string) string { + params := url.Values{} + params.Set("appid", global.Config.Payment.WxPay.SubAppId) + params.Set("redirect_uri", redirectUrl) + params.Set("response_type", "code") + params.Set("scope", "snsapi_base") + params.Set("state", "pay") + urlStr := params.Encode() + return "https://open.weixin.qq.com/connect/oauth2/authorize?" + urlStr + "#wechat_redirect" +} + +func (api wxApi) get(url string) ([]byte, error) { + resp, err := http.Get(url) + if err != nil { + return nil, err + } + + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + fmt.Println(err.Error()) + } + }(resp.Body) + + bodyBytes, err := io.ReadAll(resp.Body) + + fmt.Println(string(bodyBytes)) + + if err != nil { + return nil, errors.NewBusinessError("返回内容错误") + } + + return bodyBytes, nil +}