main
parent
44e11c3c3f
commit
2e651ca330
@ -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
|
||||
}
|
@ -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
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
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)
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
@ -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
|
||||
|
||||
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"`
|
||||
}
|
||||
|
@ -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"`
|
||||
}
|
||||
|
@ -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,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"`
|
||||
}
|
@ -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…
Reference in New Issue