Files
epay-go/internal/handler/payment/create.go
T
2026-03-28 14:55:39 +08:00

123 lines
3.4 KiB
Go

// internal/handler/payment/create.go
package payment
import (
"context"
"net/url"
"strings"
"github.com/example/epay-go/internal/service"
"github.com/example/epay-go/pkg/response"
"github.com/example/epay-go/pkg/sign"
"github.com/example/epay-go/pkg/utils"
"github.com/gin-gonic/gin"
"github.com/shopspring/decimal"
)
// CreateOrderRequest 创建订单请求(兼容原epay)
type CreateOrderRequest struct {
Pid string `form:"pid" binding:"required"` // 商户ID
Type string `form:"type" binding:"required"` // 支付类型
OutTradeNo string `form:"out_trade_no" binding:"required"`// 商户订单号
NotifyURL string `form:"notify_url" binding:"required"` // 异步通知地址
ReturnURL string `form:"return_url"` // 同步跳转地址
Name string `form:"name" binding:"required"` // 商品名称
Money string `form:"money" binding:"required"` // 金额
Sign string `form:"sign" binding:"required"` // 签名
SignType string `form:"sign_type"` // 签名类型
}
// CreateOrder 创建支付订单
func CreateOrder(c *gin.Context) {
var req CreateOrderRequest
if err := c.ShouldBind(&req); err != nil {
response.ParamError(c, "参数错误: "+err.Error())
return
}
merchantService := service.NewMerchantService()
orderService := service.NewOrderService()
// 获取商户信息
merchant, err := merchantService.GetByAPIKey(req.Pid)
if err != nil {
response.Error(c, response.CodeParamError, "商户不存在")
return
}
if merchant.Status != 1 {
response.Error(c, response.CodeForbidden, "商户已被禁用")
return
}
// 验证签名
params := url.Values{}
params.Set("pid", req.Pid)
params.Set("type", req.Type)
params.Set("out_trade_no", req.OutTradeNo)
params.Set("notify_url", req.NotifyURL)
params.Set("name", req.Name)
params.Set("money", req.Money)
if req.ReturnURL != "" {
params.Set("return_url", req.ReturnURL)
}
if !sign.VerifyMD5Sign(params, merchant.ApiKey, req.Sign) {
response.Error(c, response.CodeParamError, "签名验证失败")
return
}
// 解析金额
amount, err := decimal.NewFromString(req.Money)
if err != nil || amount.LessThanOrEqual(decimal.Zero) {
response.ParamError(c, "金额格式错误")
return
}
// 创建订单
routing, err := resolvePayRouting(req.Type, c.DefaultQuery("pay_method", ""))
if err != nil {
response.ParamError(c, err.Error())
return
}
platformBaseURL := getPaymentBaseURL(c)
orderReq := &service.CreateOrderRequest{
MerchantID: merchant.ID,
OutTradeNo: req.OutTradeNo,
Amount: amount,
Name: req.Name,
PayType: routing.PayType,
NotifyURL: req.NotifyURL,
MerchantNotifyURL: req.NotifyURL,
PlatformBaseURL: platformBaseURL,
ReturnURL: req.ReturnURL,
ClientIP: utils.GetClientIP(c),
PayMethod: routing.PayMethod,
}
orderResp, err := orderService.Create(context.Background(), orderReq)
if err != nil {
response.Error(c, response.CodeServerError, err.Error())
return
}
response.Success(c, orderResp)
}
func getPaymentBaseURL(c *gin.Context) string {
scheme := "http"
if p := c.GetHeader("X-Forwarded-Proto"); p != "" {
scheme = p
} else if c.Request.TLS != nil {
scheme = "https"
}
host := strings.TrimSpace(c.Request.Host)
if host == "" {
host = "localhost"
}
return scheme + "://" + host
}