From b8fc6a765080da1c1d7cc4ef9e231adea67f414d Mon Sep 17 00:00:00 2001 From: ziming Date: Thu, 11 Dec 2025 14:28:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E7=AC=94=E7=AB=8B=E5=87=8F=E9=87=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/pkg/helper/ip.go | 65 ++++++++++++++++++++++++++++++++++++++ internal/service/qixing.go | 8 ++++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 internal/pkg/helper/ip.go diff --git a/internal/pkg/helper/ip.go b/internal/pkg/helper/ip.go new file mode 100644 index 0000000..6600bef --- /dev/null +++ b/internal/pkg/helper/ip.go @@ -0,0 +1,65 @@ +package helper + +import ( + "net" + "strings" + + "github.com/go-kratos/kratos/v2/transport/http" +) + +// GetClientIP 获取客户端真实 IP +func GetClientIP(ctx http.Context) string { + + // 检查 X-Forwarded-For 头(多个代理时格式为 "client, proxy1, proxy2") + if xff := ctx.Header().Get("X-Forwarded-For"); xff != "" { + ips := strings.Split(xff, ",") + for _, ip := range ips { + ip = strings.TrimSpace(ip) + if ip != "" { + // 验证是否为合法 IP + if isValidIP(ip) { + return ip + } + } + } + } + + // 检查 X-Real-IP 头 + if realIP := ctx.Header().Get("X-Real-IP"); realIP != "" { + if isValidIP(realIP) { + return realIP + } + } + + // 检查 X-Forwarded + if forwarded := ctx.Header().Get("X-Forwarded"); forwarded != "" { + // 格式可能为 "for=client-ip;host=example.com;proto=https" + parts := strings.Split(forwarded, ";") + for _, part := range parts { + part = strings.TrimSpace(part) + if strings.HasPrefix(part, "for=") { + ip := strings.TrimPrefix(part, "for=") + ip = strings.Trim(ip, `"`) // 可能被引号包围 + if isValidIP(ip) { + return ip + } + } + } + } + + // 直接从 RemoteAddr 获取 + remoteAddr := ctx.Request().RemoteAddr + if ip, _, err := net.SplitHostPort(remoteAddr); err == nil { + if isValidIP(ip) { + return ip + } + } + + return "" +} + +// 验证是否为合法 IP +func isValidIP(ip string) bool { + parsedIP := net.ParseIP(ip) + return parsedIP != nil +} diff --git a/internal/service/qixing.go b/internal/service/qixing.go index 5c51940..74af1e7 100644 --- a/internal/service/qixing.go +++ b/internal/service/qixing.go @@ -8,6 +8,7 @@ import ( "io" "voucher/internal/biz" "voucher/internal/biz/bo" + "voucher/internal/pkg/helper" ) type TripartiteService struct { @@ -20,6 +21,11 @@ func NewTripartiteService(multiBiz *biz.MultiBiz) *TripartiteService { func (srv *TripartiteService) QiXingNotify(ctx http.Context) error { + ip := helper.GetClientIP(ctx) + if ip == "" { + return fmt.Errorf("获取请求 IP 失败") + } + bodyBytes, err := io.ReadAll(ctx.Request().Body) if err != nil { return fmt.Errorf("read body error: %v", err) @@ -27,7 +33,7 @@ func (srv *TripartiteService) QiXingNotify(ctx http.Context) error { var req *bo.WechatVoucherNotifyBo if err = json.Unmarshal(bodyBytes, &req); err != nil { - log.Errorf("qixing notify error:%v,body:%s", err, string(bodyBytes)) + log.Errorf("qixing notify ip:%s,error:%v,body:%s", ip, err, string(bodyBytes)) return fmt.Errorf("json unmarshal bodyBytes error: %v", err) }