elf 8 months ago
parent 44e11c3c3f
commit 2e651ca330

1
.gitignore vendored

@ -0,0 +1 @@
.DS_Store

@ -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
}

@ -1,21 +1,14 @@
package api package api
import ( import (
"bytes"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/smartwalle/alipay/v3" "gold-shop/errors"
"io" "gold-shop/request"
"jypay/errors" "gold-shop/service"
"jypay/global" "gold-shop/utils"
"jypay/model" "gold-shop/utils/payment"
"jypay/request" "gold-shop/utils/weixin"
"jypay/utils"
"log"
"net/http"
"strconv" "strconv"
"time"
) )
func Index(c *gin.Context) (utils.Data, error) { 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") return nil, errors.NewBusinessError("测试", "1122")
} }
func Pay(c *gin.Context) (utils.Data, error) { func Register(c *gin.Context) (utils.Data, error) {
req := request.OrderRequest{} mobile := c.PostForm("mobile")
err := c.BindJSON(&req) password := c.PostForm("password")
if err != nil { err := service.UserService.Register(mobile, password)
fmt.Printf("bind json err:%v", err) return nil, 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())
}
fmt.Println(result.String()) func Login(c *gin.Context) (utils.Data, error) {
order.PayUrl = result.String() mobile := c.PostForm("mobile")
order.Token = token password := c.PostForm("password")
global.DB.Save(&order) token, err := service.UserService.Login(mobile, password)
return utils.Data{"token": token}, err
}
data := utils.Data{ func GetUserInfo(c *gin.Context) (utils.Data, error) {
"pay_url": global.Config.Server.Domain + "/payment?token=" + token, user, _ := c.Get("user")
} data := utils.Data{"user": user}
return data, nil return data, nil
} }
func saveOrder(req request.OrderRequest) (*model.Order, error) { func ModifyPassword(c *gin.Context) (utils.Data, error) {
if req.OrderNo == "" { oldPassword := c.PostForm("oldPassword")
return nil, errors.NewBusinessError("订单号[orderNo]不能为空") password := c.PostForm("password")
} err := service.UserService.ModifyPassword(password, oldPassword, user(c))
return nil, err
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 Notify(c *gin.Context) { func GetProductInfo(c *gin.Context) (utils.Data, error) {
err := c.Request.ParseForm() productId := c.PostForm("productId")
if err != nil { id, _ := strconv.Atoi(productId)
log.Printf("参数错误:%v", err) product, err := service.ProductService.GetProductInfo(id)
return
}
client, err := alipay.New(global.Config.Alipay.AppId, global.Config.Alipay.PrivateKey, true)
if err != nil { if err != nil {
log.Printf("初始化支付宝失败:%v", err) return nil, err
return
} }
data := utils.Data{"product": product}
return data, nil
}
client.LoadAliPayPublicKey(global.Config.Alipay.AliPublicKey) func Payment(c *gin.Context) (utils.Data, error) {
var paymentRequest request.PaymentRequest
notification, err := client.DecodeNotification(c.Request.Form) err := c.ShouldBind(&paymentRequest)
if err != nil { if err != nil {
log.Printf("解析异步通知发生错误:%v", err) return nil, errors.NewBusinessError("参数错误")
return
} }
order := model.Order{} param := payment.WxPayParam{}
tx := global.DB.Where("order_no = ?", notification.OutTradeNo).First(&order) param.Remark = "payment"
if tx.Error != nil { param.OrderId = utils.GenerateNo("payment")
log.Printf("订单不存在:%s", notification.OutTradeNo) param.OpenId = paymentRequest.OpenID
return param.Amount = paymentRequest.Amount
param.NotifyUrl = ""
result, err := payment.PayApi.WxPay(param)
if err != nil {
return nil, err
} }
now := time.Now() if result.Status != payment.Success {
if notification.TradeStatus == "TRADE_SUCCESS" || notification.TradeStatus == "TRADE_FINISHED" { return nil, errors.NewBusinessError(result.Message)
order.PayStatus = 1
order.PayTime = &now
tx := global.DB.Save(order)
if tx.Error != nil {
log.Printf("更新订单失败:%s", notification.OutTradeNo)
return
}
} }
notifyData := make(map[string]interface{}) data := utils.Data{
notifyData["trade_no"] = notification.TradeNo "paySign": result.PaySign,
notifyData["out_trade_no"] = notification.OutTradeNo "package": result.Package,
notifyData["trade_status"] = notification.TradeStatus "signType": result.PaySignType,
notifyData["total_amount"] = notification.TotalAmount "nonceStr": result.NonceStr,
notifyResult := postToSdk(order.NotifyUrl, notifyData) "appId": result.AppId,
if notifyResult == "success" { "timeStamp": result.Timestamp,
client.ACKNotification(c.Writer)
} }
return data, nil
} }
func TestPost(c *gin.Context) (utils.Data, error) { func Order(c *gin.Context) (utils.Data, error) {
notifyData := make(map[string]interface{}) var orderRequest request.OrderRequest
notifyData["trade_no"] = "112233" err := c.ShouldBind(&orderRequest)
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)
if err != nil { if err != nil {
log.Fatalf("无法编码JSON数据%v", err) return nil, errors.NewBusinessError("参数错误")
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"
} }
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body) order, err := service.OrderService.Order(orderRequest, user(c))
if err != nil { if err != nil {
log.Fatalf("无法读取响应体内容:%v", err) return nil, err
return "fail"
} }
data := utils.Data{"orderNo": order.OrderNo}
return string(body) return data, nil
} }
func Return(c *gin.Context) { func GetWxAuthUrl(c *gin.Context) (utils.Data, error) {
token := c.Query("token") authUrl := weixin.WxApi.GetAuthUrl("")
order := model.Order{} data := utils.Data{"url": authUrl}
tx := global.DB.Where("token = ?", token).First(&order) return data, nil
if tx.Error != nil {
c.Writer.WriteHeader(http.StatusOK)
c.Writer.Write([]byte("订单不存在"))
return
}
c.Redirect(http.StatusMovedPermanently, order.ReturnUrl)
} }
func Payment(c *gin.Context) { func GetWxOpenId(c *gin.Context) (utils.Data, error) {
token := c.Query("token") code := c.Query("code")
order := model.Order{} result, err := weixin.WxApi.GetAccessToken(code)
tx := global.DB.Where("token = ?", token).First(&order) if err != nil {
fmt.Println(tx) return nil, err
if tx.Error != nil {
fmt.Println(tx.Error)
c.Writer.WriteHeader(http.StatusOK)
c.Writer.Write([]byte("订单不存在"))
return
} }
data := utils.Data{"openid": result.Openid}
c.Redirect(http.StatusMovedPermanently, order.PayUrl) return data, nil
} }

@ -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==" 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" ali-public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhgLRPY+3aSGRvlcivmcPnSSL9v3BXSea3uDOZpIpzydHxQ16c/A2m6kVh9LxlJJngXldOkO2Q4VS32RufZntc9fkjiiuUxDBlFPKl5x72eiQVoBX4yM7j0gtBlwQFezsIPD0SRC/uxj75+MtjDUupAQLA4gB4zgSDmWWYAIGQlgXXAQExr5k7P1dXrXJMP9SpIYn3Uaug5ifqxanoiDCmMp/sMFasjlVBDIpLOZuKgBwcX3d2FmhRdWIWR5UVy3IbtWuqTJ8vqH8j6Y2jVFLxBA7+woYc0s7npZ0kTa0yGXFw/9LGinSGshGUCBjuAoi67cW6YvODjYFHuGqsrXZvwIDAQAB"
database: database:
host: "47.98.244.18" host: "124.223.222.61"
port: "3306" port: "3306"
username: "liaojinling" username: "elf1990"
password: "Ljl@3115316" password: "XtN1YiaqP4BxC9MEe"
dbname: "juyou" 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"

@ -4,4 +4,7 @@ type Config struct {
Server Server Server Server
Database Database Database Database
Alipay Alipay Alipay Alipay
Jwt Jwt
Redis Redis
Payment Payment
} }

@ -0,0 +1,6 @@
package config
type Jwt struct {
Issuer string
Key string
}

@ -0,0 +1,13 @@
package config
type Payment struct {
BaseUrl string
AppKey string
SignKey string
WxPay WxPay
}
type WxPay struct {
SubAppId string
SubAppSecret string
}

@ -0,0 +1,8 @@
package config
type Redis struct {
Host string
Port string
Password string
DB int
}

@ -1,9 +1,11 @@
package global package global
import ( import (
"github.com/redis/go-redis/v9"
"gold-shop/config"
"gorm.io/gorm" "gorm.io/gorm"
"jypay/config"
) )
var Config *config.Config var Config *config.Config
var DB *gorm.DB var DB *gorm.DB
var Redis *redis.Client

@ -1,4 +1,4 @@
module jypay module gold-shop
go 1.21.1 go 1.21.1
@ -11,34 +11,45 @@ require (
) )
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/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // 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/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/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/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.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/go-sql-driver/mysql v1.7.0 // indirect
github.com/goccy/go-json v0.10.2 // 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/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.2.4 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // 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/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // 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/ncrypto v1.0.4 // indirect
github.com/smartwalle/ngx v1.0.9 // indirect github.com/smartwalle/ngx v1.0.9 // indirect
github.com/smartwalle/nsign v1.0.9 // indirect github.com/smartwalle/nsign v1.0.9 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.6.0 // indirect golang.org/x/arch v0.7.0 // indirect
golang.org/x/crypto v0.16.0 // indirect golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.19.0 // indirect golang.org/x/net v0.22.0 // indirect
golang.org/x/sys v0.15.0 // indirect golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.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
) )

@ -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.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= 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.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-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-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= 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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= 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 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 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 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= 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 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 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= 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/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 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.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 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= 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 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 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/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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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.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 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= 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/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 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.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 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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= 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/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 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.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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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 h1:IjpG3YYgUgzCfS0z/EHlUbbr0OlrmOBHUst/3FzToYE=
github.com/smartwalle/alipay/v3 v3.2.20/go.mod h1:KWg91KsY+eIOf26ZfZeH7bed1bWulGpGrL1ErHF3jWo= github.com/smartwalle/alipay/v3 v3.2.20/go.mod h1:KWg91KsY+eIOf26ZfZeH7bed1bWulGpGrL1ErHF3jWo=
github.com/smartwalle/ncrypto v1.0.4 h1:P2rqQxDepJwgeO5ShoC+wGcK2wNJDmcdBOWAksuIgx8= 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.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.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.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.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.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/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.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 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.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 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= 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= 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.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 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc=
golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= 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 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= 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 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= 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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.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 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 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.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 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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.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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

@ -2,10 +2,11 @@ package initialize
import ( import (
"fmt" "fmt"
"github.com/redis/go-redis/v9"
"gold-shop/config"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
"gorm.io/gorm" "gorm.io/gorm"
"jypay/config"
"os" "os"
) )
@ -33,3 +34,11 @@ func InitDB(conf *config.Config) *gorm.DB {
} }
return 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
})
}

@ -1,26 +1,113 @@
package main package main
import ( import (
"encoding/json"
"fmt" "fmt"
"github.com/fvbock/endless"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"jypay/api" "gold-shop/global"
"jypay/global" "gold-shop/initialize"
"jypay/initialize" "gold-shop/request"
"jypay/utils" "gold-shop/route"
"gold-shop/utils"
"net/http"
"net/url"
"time"
) )
func main() { func main() {
payOrderCommon()
}
func RunServer() {
global.Config = initialize.InitConfig() global.Config = initialize.InitConfig()
global.DB = initialize.InitDB(global.Config) global.DB = initialize.InitDB(global.Config)
fmt.Println(global.Config) global.Redis = initialize.InitRedis(global.Config)
r := gin.Default() r := gin.Default()
r.GET("/ping", utils.BuildJsonHandler(api.Index)) s := &http.Server{
r.GET("/error", utils.BuildJsonHandler(api.Error)) Addr: ":8080",
r.POST("/pay", utils.BuildJsonHandler(api.Pay)) Handler: r,
r.GET("/payment", utils.BuildHandler(api.Payment)) ReadTimeout: 10 * time.Second,
r.POST("/notify", utils.BuildHandler(api.Notify)) WriteTimeout: 10 * time.Second,
r.GET("/return", utils.BuildHandler(api.Return)) MaxHeaderBytes: 1 << 20,
r.GET("/test-post", utils.BuildJsonHandler(api.TestPost)) }
err := r.Run(":" + global.Config.Server.Port) // listen and serve on 0.0.0.0:8080 route.Initial(r)
panic(err) 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)
} }

@ -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()
}
}

@ -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")
}

@ -5,30 +5,14 @@ import (
) )
type Order struct { type Order struct {
ID uint ID uint
OrderNo string OrderNo string
UserId int UserID int
UserAccount string Amount float64
RoleName string CreatedAt time.Time
RoleId string UpdatedAt time.Time
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
} }
func (Order) TableName() string { func (Order) TableName() string {
return "outer_orders" return "orders"
} }

@ -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"
}

@ -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"
}

@ -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),
})
}

@ -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"`
}

@ -1,19 +1,6 @@
package request package request
type OrderRequest struct { type OrderRequest struct {
OrderNo string `json:"order_no"` ProductID int `json:"productId" form:"productId"`
UserId int `json:"user_id"` Num int `json:"num" form:"num"`
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"`
} }

@ -1,5 +1,7 @@
package request package request
type PaymentRequest struct { 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"`
} }

@ -0,0 +1,7 @@
package route
import "github.com/gin-gonic/gin"
func Initial(r *gin.Engine) {
h5RouteInit(r)
}

@ -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))
}
}

@ -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
}

@ -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
}

@ -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
}

@ -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='收益表';

@ -4,6 +4,7 @@ import (
"crypto/md5" "crypto/md5"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"golang.org/x/crypto/bcrypt"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
@ -23,6 +24,16 @@ func Sign(params url.Values, signKey string) string {
return Md5(params.Encode() + "&signkey=" + signKey) 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) { func Post(url string, params url.Values) {
client := &http.Client{} client := &http.Client{}
body := strings.NewReader(params.Encode()) body := strings.NewReader(params.Encode())

@ -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
}
}

@ -0,0 +1,3 @@
package payment
const Success = "10000"

@ -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
}

@ -0,0 +1,9 @@
package payment
type WxPayParam struct {
OpenId string
Amount float64
OrderId string
NotifyUrl string
Remark string
}

@ -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"`
}

@ -3,7 +3,7 @@ package utils
import ( import (
syserrors "errors" syserrors "errors"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"jypay/errors" "gold-shop/errors"
) )
type Result struct { type Result struct {
@ -14,7 +14,7 @@ type Result struct {
type Data map[string]interface{} 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) { return func(c *gin.Context) {
data, err := api(c) data, err := api(c)
result := Result{} result := Result{}
@ -22,7 +22,7 @@ func BuildJsonHandler(api func(c *gin.Context) (Data, error)) func(c *gin.Contex
result = buildErrorResult(err) result = buildErrorResult(err)
result.Data = data result.Data = data
} else { } else {
result.Code = "0000" result.Code = Success
result.Message = "成功" result.Message = "成功"
result.Data = data 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 return api
} }
@ -43,7 +43,7 @@ func buildErrorResult(err error) Result {
result.Code = businessError.Code result.Code = businessError.Code
result.Message = businessError.Message result.Message = businessError.Message
default: default:
result.Code = "1000" result.Code = Error
result.Message = "系统异常" result.Message = "系统异常"
} }
return result return result

@ -0,0 +1,6 @@
package utils
const Success string = "0000"
const Error string = "1000"
const ErrorTokenWrong string = "5000"
const ErrorTokenExpired string = "5001"

@ -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)
}

@ -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"`
}

@ -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
}
Loading…
Cancel
Save