支持 .env 配置,并完善源头对接文档与测试订单
- 增加 .env.example 与 godotenv 加载,start.sh 自动读环境变量 - 重写发给源头的开放接口对接文档 - 订单页支持创建测试订单(可直接已支付并复制店铺订单号)
This commit is contained in:
@@ -6,6 +6,7 @@ require (
|
||||
github.com/gin-contrib/cors v1.7.7
|
||||
github.com/gin-gonic/gin v1.12.0
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||
github.com/joho/godotenv v1.5.1
|
||||
golang.org/x/crypto v0.54.0
|
||||
gorm.io/driver/sqlite v1.6.0
|
||||
gorm.io/gorm v1.31.2
|
||||
|
||||
@@ -38,6 +38,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
|
||||
@@ -2,7 +2,10 @@ package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -18,7 +21,9 @@ type Config struct {
|
||||
OpenSignSkew int64
|
||||
}
|
||||
|
||||
// Load 加载配置:先尝试读取 .env,再读系统环境变量(已存在的系统环境变量优先级更高)
|
||||
func Load() *Config {
|
||||
loadDotEnv()
|
||||
return &Config{
|
||||
Port: getEnv("PORT", "8080"),
|
||||
JWTSecret: getEnv("JWT_SECRET", "affiliate-dash-dev-secret-change-me"),
|
||||
@@ -30,6 +35,32 @@ func Load() *Config {
|
||||
}
|
||||
}
|
||||
|
||||
// loadDotEnv 依次尝试常见路径,不覆盖已有环境变量
|
||||
func loadDotEnv() {
|
||||
var paths []string
|
||||
if wd, err := os.Getwd(); err == nil {
|
||||
paths = append(paths,
|
||||
filepath.Join(wd, ".env"),
|
||||
filepath.Join(wd, "..", ".env"), // 在 backend/ 下启动时读仓库根 .env
|
||||
filepath.Join(wd, "backend", ".env"), // 在仓库根启动时
|
||||
)
|
||||
}
|
||||
paths = append(paths, ".env")
|
||||
|
||||
seen := map[string]struct{}{}
|
||||
for _, p := range paths {
|
||||
abs, err := filepath.Abs(p)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[abs]; ok {
|
||||
continue
|
||||
}
|
||||
seen[abs] = struct{}{}
|
||||
_ = godotenv.Load(abs) // 忽略不存在;不覆盖已在环境中的变量
|
||||
}
|
||||
}
|
||||
|
||||
func getEnv(key, def string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
|
||||
@@ -45,30 +45,43 @@ func (h *OrderHandler) List(c *gin.Context) {
|
||||
}
|
||||
|
||||
type createOrderReq struct {
|
||||
SkinID uint `json:"skin_id" binding:"required"`
|
||||
BuyerName string `json:"buyer_name"`
|
||||
Remark string `json:"remark"`
|
||||
SkinID uint `json:"skin_id" binding:"required"`
|
||||
BuyerName string `json:"buyer_name"`
|
||||
Remark string `json:"remark"`
|
||||
Status string `json:"status"` // 管理员可传 paid 直接可发货
|
||||
DistributorID *uint `json:"distributor_id"` // 管理员可指定分销商
|
||||
}
|
||||
|
||||
func (h *OrderHandler) Create(c *gin.Context) {
|
||||
var req createOrderReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "参数错误")
|
||||
response.BadRequest(c, "参数错误:请选择商品")
|
||||
return
|
||||
}
|
||||
distributorID := middleware.GetUserID(c)
|
||||
// 管理员可指定分销商
|
||||
status := ""
|
||||
// 管理员可指定分销商、创建已支付测试单
|
||||
if middleware.GetRole(c) == model.RoleAdmin {
|
||||
if req.DistributorID != nil && *req.DistributorID > 0 {
|
||||
distributorID = *req.DistributorID
|
||||
}
|
||||
if d := c.Query("distributor_id"); d != "" {
|
||||
id, _ := strconv.ParseUint(d, 10, 64)
|
||||
distributorID = uint(id)
|
||||
}
|
||||
if req.Status == model.OrderStatusPaid {
|
||||
status = model.OrderStatusPaid
|
||||
}
|
||||
}
|
||||
if req.BuyerName == "" {
|
||||
req.BuyerName = "测试买家"
|
||||
}
|
||||
order, err := h.svc.Create(service.CreateOrderInput{
|
||||
SkinID: req.SkinID,
|
||||
DistributorID: distributorID,
|
||||
BuyerName: req.BuyerName,
|
||||
Remark: req.Remark,
|
||||
Status: status,
|
||||
})
|
||||
if err != nil {
|
||||
response.BadRequest(c, err.Error())
|
||||
|
||||
@@ -31,6 +31,8 @@ type CreateOrderInput struct {
|
||||
DistributorID uint
|
||||
BuyerName string
|
||||
Remark string
|
||||
// Status 可选:pending(默认)/ paid(联调测试可直接创建可发货订单)
|
||||
Status string
|
||||
}
|
||||
|
||||
func (s *OrderService) List(q OrderListQuery) ([]model.Order, int64, error) {
|
||||
@@ -71,6 +73,11 @@ func (s *OrderService) Create(in CreateOrderInput) (*model.Order, error) {
|
||||
return nil, errors.New("库存不足")
|
||||
}
|
||||
|
||||
status := model.OrderStatusPending
|
||||
if in.Status == model.OrderStatusPaid {
|
||||
status = model.OrderStatusPaid
|
||||
}
|
||||
|
||||
order := &model.Order{
|
||||
OrderNo: generateOrderNo(),
|
||||
SkinID: in.SkinID,
|
||||
@@ -78,7 +85,7 @@ func (s *OrderService) Create(in CreateOrderInput) (*model.Order, error) {
|
||||
BuyerName: in.BuyerName,
|
||||
Amount: skin.Price,
|
||||
CommissionAmt: skin.Price * skin.Commission,
|
||||
Status: model.OrderStatusPending,
|
||||
Status: status,
|
||||
Remark: in.Remark,
|
||||
}
|
||||
|
||||
@@ -99,6 +106,8 @@ func (s *OrderService) Create(in CreateOrderInput) (*model.Order, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 带回商品信息,方便前端展示 sku / 订单号联调
|
||||
_ = s.db.Preload("Skin").First(order, order.ID).Error
|
||||
return order, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user