重构日志与可观测性体系
新增单行文本编码器与结构化 GORM 日志,统一错误记录与请求日志策略,收紧日志文件权限并修复按天切分与压缩,支付回调参数脱敏,生产强制阿里云短信,RequestID 校验防注入,日志文案中文化。
This commit is contained in:
@@ -65,6 +65,7 @@ func parseQuery(c *gin.Context) (Query, bool) {
|
||||
}
|
||||
|
||||
func writeAuditError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -170,6 +170,7 @@ func isHTTPSRequest(c *gin.Context) bool {
|
||||
}
|
||||
|
||||
func writeAdminAuthError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -27,6 +27,7 @@ func (h *Handler) Summary(c *gin.Context) {
|
||||
}
|
||||
|
||||
func writeDashboardError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -228,6 +228,7 @@ func parseDateRange(c *gin.Context, defaultLookbackDays int) (time.Time, time.Ti
|
||||
}
|
||||
|
||||
func writeFinanceError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -163,6 +163,7 @@ func parseID(c *gin.Context) (uint64, bool) {
|
||||
}
|
||||
|
||||
func writeError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -110,6 +110,7 @@ func currentAdminID(c *gin.Context) (uint64, bool) {
|
||||
}
|
||||
|
||||
func writeNotificationError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -154,6 +154,7 @@ func currentAdminID(c *gin.Context) (uint64, bool) {
|
||||
}
|
||||
|
||||
func writePushError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -120,6 +120,7 @@ func parseID(c *gin.Context) (uint64, bool) {
|
||||
}
|
||||
|
||||
func writeError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -236,6 +236,7 @@ func auditMeta(c *gin.Context) AuditMeta {
|
||||
}
|
||||
|
||||
func writeAdminUserError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -29,6 +29,7 @@ func (h *Handler) List(c *gin.Context) {
|
||||
|
||||
result, err := h.service.List(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "获取公告列表失败")
|
||||
return
|
||||
}
|
||||
@@ -67,6 +68,7 @@ func (h *Handler) AdminList(c *gin.Context) {
|
||||
|
||||
result, err := h.service.AdminList(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "获取公告列表失败")
|
||||
return
|
||||
}
|
||||
@@ -111,6 +113,7 @@ func (h *Handler) Create(c *gin.Context) {
|
||||
|
||||
announcement, err := h.service.Create(c.Request.Context(), req, adminID)
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "创建公告失败")
|
||||
return
|
||||
}
|
||||
@@ -134,6 +137,7 @@ func (h *Handler) Update(c *gin.Context) {
|
||||
|
||||
announcement, err := h.service.Update(c.Request.Context(), id, req)
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "更新公告失败")
|
||||
return
|
||||
}
|
||||
@@ -150,6 +154,7 @@ func (h *Handler) Publish(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.service.Publish(c.Request.Context(), id); err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "发布公告失败")
|
||||
return
|
||||
}
|
||||
@@ -166,6 +171,7 @@ func (h *Handler) Archive(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.service.Archive(c.Request.Context(), id); err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "归档公告失败")
|
||||
return
|
||||
}
|
||||
@@ -182,6 +188,7 @@ func (h *Handler) Unarchive(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.service.Unarchive(c.Request.Context(), id); err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "取消归档公告失败")
|
||||
return
|
||||
}
|
||||
@@ -198,6 +205,7 @@ func (h *Handler) Delete(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.service.Delete(c.Request.Context(), id); err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "删除公告失败")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -212,6 +212,7 @@ func (h *Handler) ResetPassword(c *gin.Context) {
|
||||
}
|
||||
|
||||
func writeAuthError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库或 Redis 未连接")
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"hfb_sys/backend/internal/captcha"
|
||||
smsprovider "hfb_sys/backend/internal/integrations/sms"
|
||||
"hfb_sys/backend/internal/logging"
|
||||
"hfb_sys/backend/internal/model"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
@@ -120,7 +121,15 @@ func (s *Service) SendSMSCode(ctx context.Context, phone string, captchaID strin
|
||||
}
|
||||
if err := s.sms.SendLoginCode(ctx, phone, code); err != nil {
|
||||
if s.log != nil {
|
||||
s.log.Warn("sms login code send failed", zap.String("phone", PublicPhone(phone)), zap.Error(err))
|
||||
fields := []zap.Field{
|
||||
zap.String("module", "auth"),
|
||||
zap.String("phone", PublicPhone(phone)),
|
||||
zap.Error(err),
|
||||
}
|
||||
if requestID := logging.RequestIDFromContext(ctx); requestID != "" {
|
||||
fields = append(fields, zap.String("request_id", requestID))
|
||||
}
|
||||
s.log.Warn("短信验证码发送失败", fields...)
|
||||
}
|
||||
if smsprovider.IsProviderRateLimited(err) {
|
||||
pipe := s.redis.TxPipeline()
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func writeChatError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "聊天服务暂时不可用")
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"hfb_sys/backend/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -19,7 +21,8 @@ func (h *Handler) CreateQrCodeHandler(c *gin.Context) {
|
||||
adminID := c.GetUint64("admin_id")
|
||||
qrcode, err := h.service.repo.CreateQrCode(c.Request.Context(), adminID, req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "聊天二维码服务暂时不可用")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -37,7 +40,8 @@ func (h *Handler) BatchCreateQrCodeHandler(c *gin.Context) {
|
||||
adminID := c.GetUint64("admin_id")
|
||||
qrcodes, err := h.service.repo.BatchCreateQrCode(c.Request.Context(), adminID, req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "聊天二维码服务暂时不可用")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -54,7 +58,8 @@ func (h *Handler) BatchDeleteQrCodeHandler(c *gin.Context) {
|
||||
|
||||
deleted, err := h.service.repo.BatchDeleteQrCodes(c.Request.Context(), req.IDs)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "聊天二维码服务暂时不可用")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -71,7 +76,8 @@ func (h *Handler) ListQrCodesHandler(c *gin.Context) {
|
||||
|
||||
qrcodes, total, err := h.service.repo.ListQrCodes(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "聊天二维码服务暂时不可用")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -89,7 +95,8 @@ func (h *Handler) ListQrCodesHandler(c *gin.Context) {
|
||||
func (h *Handler) GetQrCodeStatsHandler(c *gin.Context) {
|
||||
stats, err := h.service.repo.GetQrCodeStats(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "聊天二维码服务暂时不可用")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,7 +131,8 @@ func (h *Handler) RecognizeQrCodeGroupNameHandler(c *gin.Context) {
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": "PaddleOCR 服务暂时不可用"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "聊天二维码服务暂时不可用")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -167,7 +175,8 @@ func (h *Handler) SubmitOCRJobHandler(c *gin.Context) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "OCR 任务不存在或已过期"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "聊天二维码服务暂时不可用")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -188,7 +197,8 @@ func (h *Handler) GetOCRJobResultHandler(c *gin.Context) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "OCR 任务不存在或已过期"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "聊天二维码服务暂时不可用")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -218,7 +228,8 @@ func (h *Handler) UpdateQrCodeHandler(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "已发放的二维码不能改回待用"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "聊天二维码服务暂时不可用")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -238,7 +249,8 @@ func (h *Handler) DeleteQrCodeHandler(c *gin.Context) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "二维码不存在"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "聊天二维码服务暂时不可用")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"hfb_sys/backend/internal/listingstatus"
|
||||
"hfb_sys/backend/internal/logging"
|
||||
"hfb_sys/backend/internal/model"
|
||||
"hfb_sys/backend/internal/modules/adminnotification"
|
||||
"hfb_sys/backend/internal/modules/notification"
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"hfb_sys/backend/internal/modules/wallet"
|
||||
"hfb_sys/backend/pkg/money"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
@@ -453,7 +454,13 @@ func (r *Repository) startRefundBestEffort(ctx context.Context, action *refundAc
|
||||
return
|
||||
}
|
||||
if _, err := r.refundStarter.StartRefund(ctx, action.OrderID, action.RefundAmountCent, action.BizType, action.Remark); err != nil {
|
||||
log.Printf("[dispute] start refund failed order_id=%d biz_type=%s amount_cent=%d err=%v", action.OrderID, action.BizType, action.RefundAmountCent, err)
|
||||
logging.FromContext(ctx).Error("争议退款提交失败",
|
||||
zap.String("module", "dispute"),
|
||||
zap.Uint64("order_id", action.OrderID),
|
||||
zap.String("biz_type", action.BizType),
|
||||
zap.Int64("amount_cent", action.RefundAmountCent),
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -226,6 +226,7 @@ func parsePagination(c *gin.Context) (int, int) {
|
||||
}
|
||||
|
||||
func writeDisputeError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -94,7 +94,7 @@ func (h *Handler) writeObject(c *gin.Context, publicOnly bool) {
|
||||
}
|
||||
|
||||
func writeFileError(c *gin.Context, err error) {
|
||||
_ = c.Error(err)
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "文件存储未连接")
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
)
|
||||
|
||||
func writeListingError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package listing
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
_ "embed"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -116,6 +116,7 @@ func externalUploadIPAllowed(clientIP string, allowed []string) bool {
|
||||
}
|
||||
|
||||
func writeExternalUploadAuthError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch err {
|
||||
case errExternalUploadForbiddenIP:
|
||||
response.Error(c, http.StatusForbidden, "forbidden", "来源 IP 不允许访问")
|
||||
|
||||
@@ -22,6 +22,7 @@ func NewHandler(service *Service) *Handler {
|
||||
func (h *Handler) ListCategories(c *gin.Context) {
|
||||
items, err := h.service.ListPublicCategories(c.Request.Context())
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "获取分类失败")
|
||||
return
|
||||
}
|
||||
@@ -36,6 +37,7 @@ func (h *Handler) ListProducts(c *gin.Context) {
|
||||
query.Page, query.PageSize = parsePagination(c)
|
||||
result, err := h.service.ListPublicProducts(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "获取商品列表失败")
|
||||
return
|
||||
}
|
||||
@@ -84,6 +86,7 @@ func (h *Handler) ListMyOrders(c *gin.Context) {
|
||||
query.Page, query.PageSize = parsePagination(c)
|
||||
result, err := h.service.ListOrdersForUser(c.Request.Context(), userID, query)
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "获取订单列表失败")
|
||||
return
|
||||
}
|
||||
@@ -133,6 +136,7 @@ func (h *Handler) CancelMyOrder(c *gin.Context) {
|
||||
func (h *Handler) AdminListCategories(c *gin.Context) {
|
||||
items, err := h.service.AdminListCategories(c.Request.Context())
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "获取分类失败")
|
||||
return
|
||||
}
|
||||
@@ -194,6 +198,7 @@ func (h *Handler) AdminListProducts(c *gin.Context) {
|
||||
query.Page, query.PageSize = parsePagination(c)
|
||||
result, err := h.service.AdminListProducts(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "获取商品列表失败")
|
||||
return
|
||||
}
|
||||
@@ -273,6 +278,7 @@ func (h *Handler) AdminListOrders(c *gin.Context) {
|
||||
query.Page, query.PageSize = parsePagination(c)
|
||||
result, err := h.service.AdminListOrders(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "获取订单列表失败")
|
||||
return
|
||||
}
|
||||
@@ -340,6 +346,7 @@ func (h *Handler) AdminCancelOrder(c *gin.Context) {
|
||||
func (h *Handler) AdminGetConfig(c *gin.Context) {
|
||||
item, err := h.service.GetConfig(c.Request.Context())
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "获取配置失败")
|
||||
return
|
||||
}
|
||||
@@ -354,6 +361,7 @@ func (h *Handler) AdminUpdateConfig(c *gin.Context) {
|
||||
}
|
||||
item, err := h.service.UpdateConfig(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.InternalServerError(c, "更新配置失败")
|
||||
return
|
||||
}
|
||||
@@ -361,6 +369,7 @@ func (h *Handler) AdminUpdateConfig(c *gin.Context) {
|
||||
}
|
||||
|
||||
func writeError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrProductNotFound), errors.Is(err, ErrOrderNotFound):
|
||||
response.NotFound(c, err.Error())
|
||||
|
||||
@@ -104,6 +104,7 @@ func currentUserID(c *gin.Context) (uint64, bool) {
|
||||
}
|
||||
|
||||
func writeNotificationError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func writeOrderError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -2,9 +2,11 @@ package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"hfb_sys/backend/internal/logging"
|
||||
"hfb_sys/backend/internal/model"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (r *Repository) prepareRefund(order *model.RentalOrder, amountCent int64, bizType string, remark string) (*refundAction, error) {
|
||||
@@ -30,6 +32,12 @@ func (r *Repository) startRefundBestEffort(ctx context.Context, action *refundAc
|
||||
return
|
||||
}
|
||||
if _, err := r.refundStarter.StartRefund(ctx, action.OrderID, action.RefundAmountCent, action.BizType, action.Remark); err != nil {
|
||||
log.Printf("[order] start refund failed order_id=%d biz_type=%s amount_cent=%d err=%v", action.OrderID, action.BizType, action.RefundAmountCent, err)
|
||||
logging.FromContext(ctx).Error("订单退款提交失败",
|
||||
zap.String("module", "order"),
|
||||
zap.Uint64("order_id", action.OrderID),
|
||||
zap.String("biz_type", action.BizType),
|
||||
zap.Int64("amount_cent", action.RefundAmountCent),
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,14 +186,13 @@ func (h *Handler) LeshuaNotify(c *gin.Context) {
|
||||
}
|
||||
rawPayload := string(body)
|
||||
contentType := c.GetHeader("Content-Type")
|
||||
h.log().Info("payment notify received", notifyLogFields(c.Request.Context(), "leshua", params, contentType, len(body))...)
|
||||
result, err := h.service.HandleLeshuaNotify(c.Request.Context(), params, rawPayload, contentType)
|
||||
if err != nil || result == nil || !result.OK {
|
||||
h.log().Warn("payment notify failed", notifyLogFields(c.Request.Context(), "leshua", params, contentType, len(body), zap.Error(err))...)
|
||||
h.log().Warn("支付回调处理失败", notifyLogFields(c.Request.Context(), "leshua", params, contentType, len(body), zap.Error(err))...)
|
||||
c.String(http.StatusOK, "FAIL")
|
||||
return
|
||||
}
|
||||
h.log().Info("payment notify processed", notifyLogFields(c.Request.Context(), "leshua", params, contentType, len(body))...)
|
||||
h.log().Info("支付回调处理完成", notifyLogFields(c.Request.Context(), "leshua", params, contentType, len(body))...)
|
||||
c.String(http.StatusOK, result.Message)
|
||||
}
|
||||
|
||||
@@ -211,14 +210,13 @@ func (h *Handler) LakalaNotify(c *gin.Context) {
|
||||
rawPayload := string(body)
|
||||
contentType := c.GetHeader("Content-Type")
|
||||
authorization := c.GetHeader("Authorization")
|
||||
h.log().Info("payment notify received", notifyLogFields(c.Request.Context(), "lakala", params, contentType, len(body))...)
|
||||
result, err := h.service.HandleNotify(c.Request.Context(), "lakala", params, rawPayload, contentType, authorization)
|
||||
if err != nil || result == nil || !result.OK {
|
||||
h.log().Warn("payment notify failed", notifyLogFields(c.Request.Context(), "lakala", params, contentType, len(body), zap.Error(err))...)
|
||||
h.log().Warn("支付回调处理失败", notifyLogFields(c.Request.Context(), "lakala", params, contentType, len(body), zap.Error(err))...)
|
||||
c.JSON(http.StatusOK, gin.H{"code": "FAIL", "message": "失败"})
|
||||
return
|
||||
}
|
||||
h.log().Info("payment notify processed", notifyLogFields(c.Request.Context(), "lakala", params, contentType, len(body))...)
|
||||
h.log().Info("支付回调处理完成", notifyLogFields(c.Request.Context(), "lakala", params, contentType, len(body))...)
|
||||
c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": "执行成功"})
|
||||
}
|
||||
|
||||
@@ -236,14 +234,13 @@ func (h *Handler) ShunchengNotify(c *gin.Context) {
|
||||
rawPayload := string(body)
|
||||
contentType := c.GetHeader("Content-Type")
|
||||
authorization := c.GetHeader("Authorization")
|
||||
h.log().Info("payment notify received", notifyLogFields(c.Request.Context(), "shuncheng", params, contentType, len(body))...)
|
||||
result, err := h.service.HandleNotify(c.Request.Context(), "shuncheng", params, rawPayload, contentType, authorization)
|
||||
if err != nil || result == nil || !result.OK {
|
||||
h.log().Warn("payment notify failed", notifyLogFields(c.Request.Context(), "shuncheng", params, contentType, len(body), zap.Error(err))...)
|
||||
h.log().Warn("支付回调处理失败", notifyLogFields(c.Request.Context(), "shuncheng", params, contentType, len(body), zap.Error(err))...)
|
||||
c.String(http.StatusOK, "FAIL")
|
||||
return
|
||||
}
|
||||
h.log().Info("payment notify processed", notifyLogFields(c.Request.Context(), "shuncheng", params, contentType, len(body))...)
|
||||
h.log().Info("支付回调处理完成", notifyLogFields(c.Request.Context(), "shuncheng", params, contentType, len(body))...)
|
||||
c.String(http.StatusOK, result.Message)
|
||||
}
|
||||
|
||||
@@ -295,6 +292,7 @@ func parseAdminPaymentQuery(c *gin.Context) (AdminPaymentQuery, bool) {
|
||||
}
|
||||
|
||||
func writePaymentError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -60,11 +60,6 @@ func (r *Repository) StartMohong(ctx context.Context, userID uint64, orderID uin
|
||||
return nil, ErrPaymentUnavailable
|
||||
}
|
||||
|
||||
r.log().Info("mohong payment start", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
)...,
|
||||
)...)
|
||||
resp, err := runtimeConfig.Channel.CreatePayment(ctx, channelCreatePaymentRequest{
|
||||
ThirdOrderID: payment.ThirdOrderID,
|
||||
AmountCent: payment.AmountCent,
|
||||
@@ -78,7 +73,7 @@ func (r *Repository) StartMohong(ctx context.Context, userID uint64, orderID uin
|
||||
})
|
||||
if err != nil {
|
||||
_ = r.markPaymentFailed(ctx, payment.ID, nil, err.Error())
|
||||
r.log().Warn("mohong payment request failed", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("魔哄支付下单失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
[]zap.Field{zap.Error(err)},
|
||||
@@ -107,6 +102,11 @@ func (r *Repository) StartMohong(ctx context.Context, userID uint64, orderID uin
|
||||
return nil, err
|
||||
}
|
||||
r.recordConfigUsage(ctx, runtimeConfig, latest)
|
||||
r.log().Info("魔哄支付下单完成", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(latest),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
)...,
|
||||
)...)
|
||||
dto := toDTO(*latest)
|
||||
return &dto, nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@ package payment
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
|
||||
@@ -33,7 +37,7 @@ func (r *Repository) HandleNotify(ctx context.Context, provider string, params m
|
||||
|
||||
if amount := parseCent(params["amount"]); amount > 0 && amount != payment.AmountCent {
|
||||
if err := r.recordNotifyDiagnostic(ctx, payment.ID, params, rawPayload, contentType, verify, "amount_mismatch"); err != nil {
|
||||
r.log().Warn("payment notify diagnostic save failed", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("支付回调诊断保存失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
[]zap.Field{
|
||||
@@ -116,20 +120,18 @@ func (r *Repository) verifyNotify(ctx context.Context, payment *model.PaymentOrd
|
||||
}
|
||||
verify, err := runtimeConfig.Channel.VerifyNotify(params, rawPayload, contentType, authorization)
|
||||
if err != nil || !verify.OK {
|
||||
r.log().Warn("payment notify verify failed", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("支付回调验签失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
[]zap.Field{
|
||||
zap.String("sign_got", verify.Got),
|
||||
zap.String("sign_expected", firstNonEmpty(verify.Expected["notify_key"], verify.Expected["notify_cert"], verify.Expected["error"])),
|
||||
zap.Bool("signature_present", verify.Got != ""),
|
||||
zap.Strings("param_keys", verify.ParamKeys),
|
||||
zap.String("sign_base_string", firstNonEmpty(verify.BaseString["notify_key"], verify.BaseString["notify_cert"])),
|
||||
zap.Error(err),
|
||||
},
|
||||
)...,
|
||||
)...)
|
||||
if err := r.recordNotifyDiagnostic(ctx, payment.ID, params, rawPayload, contentType, verify, "verify_failed"); err != nil {
|
||||
r.log().Warn("payment notify diagnostic save failed", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("支付回调诊断保存失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
[]zap.Field{
|
||||
@@ -141,12 +143,6 @@ func (r *Repository) verifyNotify(ctx context.Context, payment *model.PaymentOrd
|
||||
}
|
||||
return verify, ErrPaymentVerifyFailed
|
||||
}
|
||||
r.log().Info("payment notify verified", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
[]zap.Field{zap.String("matched_key", verify.MatchedKey)},
|
||||
)...,
|
||||
)...)
|
||||
return verify, nil
|
||||
}
|
||||
func (r *Repository) recordNotifyDiagnostic(ctx context.Context, paymentID uint64, params map[string]string, rawPayload string, contentType string, verify channelVerifyNotifyResult, status string) error {
|
||||
@@ -159,13 +155,41 @@ func (r *Repository) recordNotifyDiagnostic(ctx context.Context, paymentID uint6
|
||||
Update("raw_response", jsonMap(raw)).Error
|
||||
}
|
||||
func withNotifyDiagnostic(params map[string]string, rawPayload string, contentType string, verify channelVerifyNotifyResult, status string) map[string]string {
|
||||
raw := withRawSource(params, channelSourceNotify)
|
||||
raw := withRawSource(redactNotifyParams(params), channelSourceNotify)
|
||||
raw["_notify_diagnostic_status"] = status
|
||||
raw["_raw_payload"] = rawPayload
|
||||
raw["_raw_content_type"] = contentType
|
||||
raw["_sign_got"] = verify.Got
|
||||
raw["_raw_payload_size"] = strconv.Itoa(len(rawPayload))
|
||||
raw["_raw_payload_sha256"] = shortDigest(rawPayload)
|
||||
raw["_signature_present"] = strconv.FormatBool(verify.Got != "")
|
||||
raw["_sign_matched_key"] = verify.MatchedKey
|
||||
raw["_sign_expected"] = jsonString(verify.Expected)
|
||||
raw["_sign_base_strings"] = jsonString(verify.BaseString)
|
||||
raw["_sign_param_keys"] = strings.Join(verify.ParamKeys, ",")
|
||||
return raw
|
||||
}
|
||||
|
||||
func redactNotifyParams(params map[string]string) map[string]string {
|
||||
allowed := map[string]bool{
|
||||
"service": true, "merchant_id": true, "third_order_id": true,
|
||||
"provider_order_id": true, "leshua_order_id": true, "schc_order_id": true,
|
||||
"merchant_refund_id": true, "provider_refund_id": true,
|
||||
"leshua_refund_id": true, "schc_refund_id": true,
|
||||
"status": true, "amount": true, "refund_amount": true,
|
||||
"pay_time": true, "refund_time": true,
|
||||
"code": true, "resp_code": true, "result_code": true, "error_code": true,
|
||||
}
|
||||
redacted := make(map[string]string, len(allowed))
|
||||
for key, value := range params {
|
||||
lowerKey := strings.ToLower(key)
|
||||
if allowed[lowerKey] {
|
||||
redacted[key] = value
|
||||
}
|
||||
}
|
||||
return redacted
|
||||
}
|
||||
|
||||
func shortDigest(value string) string {
|
||||
if value == "" {
|
||||
return ""
|
||||
}
|
||||
sum := sha256.Sum256([]byte(value))
|
||||
return hex.EncodeToString(sum[:8])
|
||||
}
|
||||
|
||||
@@ -60,11 +60,6 @@ func (r *Repository) Start(ctx context.Context, userID uint64, orderID uint64, r
|
||||
return nil, ErrPaymentUnavailable
|
||||
}
|
||||
|
||||
r.log().Info("payment start", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
)...,
|
||||
)...)
|
||||
resp, err := runtimeConfig.Channel.CreatePayment(ctx, channelCreatePaymentRequest{
|
||||
ThirdOrderID: payment.ThirdOrderID,
|
||||
AmountCent: payment.AmountCent,
|
||||
@@ -78,7 +73,7 @@ func (r *Repository) Start(ctx context.Context, userID uint64, orderID uint64, r
|
||||
})
|
||||
if err != nil {
|
||||
_ = r.markPaymentFailed(ctx, payment.ID, nil, err.Error())
|
||||
r.log().Warn("payment request failed", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("支付下单请求失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
[]zap.Field{zap.Error(err)},
|
||||
@@ -88,7 +83,7 @@ func (r *Repository) Start(ctx context.Context, userID uint64, orderID uint64, r
|
||||
}
|
||||
if !resp.OK {
|
||||
_ = r.markPaymentFailed(ctx, payment.ID, resp.Raw, resp.ErrorMessage)
|
||||
r.log().Warn("payment rejected", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("支付下单被渠道拒绝", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
[]zap.Field{
|
||||
@@ -117,7 +112,7 @@ func (r *Repository) Start(ctx context.Context, userID uint64, orderID uint64, r
|
||||
return nil, err
|
||||
}
|
||||
r.recordConfigUsage(ctx, runtimeConfig, latest)
|
||||
r.log().Info("payment result", paymentLogFields(ctx, appendFields(
|
||||
r.log().Info("支付下单完成", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(latest),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
)...,
|
||||
|
||||
@@ -31,7 +31,7 @@ func (r *Repository) StartRefund(ctx context.Context, orderID uint64, refundAmou
|
||||
if existing {
|
||||
latest, syncErr := r.syncRefundPayment(ctx, refundOrder, refundOrder.Status != "refunded")
|
||||
if syncErr != nil {
|
||||
r.log().Warn("payment existing refund sync failed", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("已有退款单同步失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(refundOrder),
|
||||
[]zap.Field{zap.String("biz_type", bizType), zap.Error(syncErr)},
|
||||
)...,
|
||||
@@ -65,19 +65,9 @@ func (r *Repository) StartRefund(ctx context.Context, orderID uint64, refundAmou
|
||||
return &dto, nil
|
||||
}
|
||||
|
||||
r.log().Info("payment refund start", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(refundOrder),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
[]zap.Field{
|
||||
zap.String("merchant_refund_id", refundOrder.ThirdOrderID),
|
||||
zap.String("origin_third_order_id", originalPayment.ThirdOrderID),
|
||||
zap.String("origin_provider_order_id", refundOriginProviderOrderID(originalPayment)),
|
||||
},
|
||||
)...,
|
||||
)...)
|
||||
r.recordConfigUsage(ctx, runtimeConfig, refundOrder)
|
||||
if err := r.markOrderRefunding(ctx, orderID, refundAmountCent); err != nil {
|
||||
r.log().Warn("payment mark order refunding failed", paymentLogFields(ctx,
|
||||
r.log().Warn("订单退款状态更新失败", paymentLogFields(ctx,
|
||||
zap.Uint64("order_id", orderID),
|
||||
zap.Int64("refund_amount_cent", refundAmountCent),
|
||||
zap.Error(err),
|
||||
@@ -86,7 +76,7 @@ func (r *Repository) StartRefund(ctx context.Context, orderID uint64, refundAmou
|
||||
|
||||
if runtimeConfig.Channel == nil {
|
||||
if err := r.markRefundFailed(ctx, refundOrder.ID, orderID, refundAmountCent, map[string]string{"error": "payment channel unavailable"}, nil); err != nil {
|
||||
r.log().Warn("payment mark refund failed status failed", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("退款失败状态保存失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(refundOrder),
|
||||
[]zap.Field{zap.Error(err)},
|
||||
)...,
|
||||
@@ -109,13 +99,13 @@ func (r *Repository) StartRefund(ctx context.Context, orderID uint64, refundAmou
|
||||
rawRequest = resp.RawRequest
|
||||
}
|
||||
if markErr := r.markRefundFailed(ctx, refundOrder.ID, orderID, refundAmountCent, map[string]string{"error": err.Error()}, rawRequest); markErr != nil {
|
||||
r.log().Warn("payment mark refund failed status failed", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("退款失败状态保存失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(refundOrder),
|
||||
[]zap.Field{zap.Error(markErr)},
|
||||
)...,
|
||||
)...)
|
||||
}
|
||||
r.log().Warn("payment refund request failed", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("退款渠道请求失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(refundOrder),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
[]zap.Field{zap.Error(err)},
|
||||
@@ -125,13 +115,13 @@ func (r *Repository) StartRefund(ctx context.Context, orderID uint64, refundAmou
|
||||
}
|
||||
if !resp.OK {
|
||||
if markErr := r.markRefundFailed(ctx, refundOrder.ID, orderID, refundAmountCent, resp.Raw, resp.RawRequest); markErr != nil {
|
||||
r.log().Warn("payment mark refund rejected status failed", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("退款拒绝状态保存失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(refundOrder),
|
||||
[]zap.Field{zap.Error(markErr)},
|
||||
)...,
|
||||
)...)
|
||||
}
|
||||
r.log().Warn("payment refund rejected", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("退款被渠道拒绝", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(refundOrder),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
[]zap.Field{
|
||||
@@ -153,7 +143,7 @@ func (r *Repository) StartRefund(ctx context.Context, orderID uint64, refundAmou
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.log().Info("payment refund result", paymentLogFields(ctx, appendFields(
|
||||
r.log().Info("退款提交完成", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(refundOrder),
|
||||
runtimeConfigFields(runtimeConfig),
|
||||
[]zap.Field{
|
||||
@@ -308,7 +298,7 @@ func (r *Repository) syncRefundPayment(ctx context.Context, payment *model.Payme
|
||||
if err != nil {
|
||||
if resp != nil && resp.RawRequest != nil {
|
||||
if updateErr := r.updateRefundRawRequest(ctx, payment.ID, resp.RawRequest); updateErr != nil {
|
||||
r.log().Warn("payment refund query raw request update failed", paymentLogFields(ctx, appendFields(
|
||||
r.log().Warn("退款查询诊断保存失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
[]zap.Field{zap.Error(updateErr)},
|
||||
)...,
|
||||
|
||||
@@ -255,7 +255,7 @@ func (r *Repository) recordConfigUsage(ctx context.Context, runtimeConfig *runti
|
||||
return
|
||||
}
|
||||
if err := r.configRepo.RecordUsage(ctx, runtimeConfig.ID, payment.ID, runtimeConfig.Provider, runtimeConfig.MerchantID, payment.AmountCent, payment.BizType); err != nil {
|
||||
r.log().Warn("payment config usage record failed", paymentLogFields(ctx,
|
||||
r.log().Warn("支付配置使用记录保存失败", paymentLogFields(ctx,
|
||||
zap.Uint64("payment_config_id", runtimeConfig.ID),
|
||||
zap.Uint64("payment_id", payment.ID),
|
||||
zap.Error(err),
|
||||
|
||||
@@ -165,6 +165,7 @@ func parseID(c *gin.Context) (uint64, bool) {
|
||||
}
|
||||
|
||||
func writeError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch err {
|
||||
case ErrAccountNotFound:
|
||||
response.NotFound(c, "收款账号不存在")
|
||||
|
||||
@@ -40,6 +40,7 @@ func (h *Handler) List(c *gin.Context) {
|
||||
|
||||
resp, err := h.service.List(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.Error(c, http.StatusInternalServerError, "internal_error", "查询失败")
|
||||
return
|
||||
}
|
||||
@@ -78,6 +79,7 @@ func (h *Handler) Get(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.Error(c, http.StatusInternalServerError, "internal_error", "查询失败")
|
||||
return
|
||||
}
|
||||
@@ -99,16 +101,19 @@ func (h *Handler) ExportBackup(c *gin.Context) {
|
||||
|
||||
backup, err := h.service.ExportBackup(c.Request.Context(), adminID, auditMeta(c))
|
||||
if err == ErrDecryptionFailed {
|
||||
response.RecordError(c, err)
|
||||
response.Error(c, http.StatusInternalServerError, "decrypt_failed", "密钥解密失败")
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.Error(c, http.StatusInternalServerError, "internal_error", "导出失败")
|
||||
return
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(backup, "", " ")
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.Error(c, http.StatusInternalServerError, "internal_error", "导出失败")
|
||||
return
|
||||
}
|
||||
@@ -148,10 +153,12 @@ func (h *Handler) ImportBackup(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if err == ErrEncryptionFailed {
|
||||
response.RecordError(c, err)
|
||||
response.Error(c, http.StatusInternalServerError, "encrypt_failed", "密钥加密失败")
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.Error(c, http.StatusInternalServerError, "internal_error", "导入失败")
|
||||
return
|
||||
}
|
||||
@@ -187,6 +194,7 @@ func (h *Handler) Create(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.Error(c, http.StatusInternalServerError, "internal_error", "创建失败")
|
||||
return
|
||||
}
|
||||
@@ -230,6 +238,7 @@ func (h *Handler) Update(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.Error(c, http.StatusInternalServerError, "internal_error", "更新失败")
|
||||
return
|
||||
}
|
||||
@@ -266,6 +275,7 @@ func (h *Handler) Delete(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
response.RecordError(c, err)
|
||||
response.Error(c, http.StatusInternalServerError, "internal_error", "删除失败")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -179,6 +179,7 @@ func (h *Handler) ListForSeller(c *gin.Context) {
|
||||
}
|
||||
|
||||
func writePickupError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -69,6 +69,7 @@ func currentUserID(c *gin.Context) (uint64, bool) {
|
||||
}
|
||||
|
||||
func writeRealnameError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"hfb_sys/backend/internal/logging"
|
||||
"hfb_sys/backend/internal/model"
|
||||
|
||||
"go.uber.org/zap"
|
||||
@@ -61,13 +62,17 @@ func (s *Service) Start(ctx context.Context, userID uint64, name string, idNo st
|
||||
})
|
||||
if err != nil {
|
||||
if s.log != nil {
|
||||
s.log.Warn(
|
||||
"realname provider verify failed",
|
||||
fields := []zap.Field{
|
||||
zap.String("module", "realname"),
|
||||
zap.String("provider", s.provider.Name()),
|
||||
zap.Uint64("user_id", userID),
|
||||
zap.String("masked_id_no", maskIDNo(idNo)),
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
if requestID := logging.RequestIDFromContext(ctx); requestID != "" {
|
||||
fields = append(fields, zap.String("request_id", requestID))
|
||||
}
|
||||
s.log.Warn("实名认证服务调用失败", fields...)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ func parseID(c *gin.Context) (uint64, bool) {
|
||||
}
|
||||
|
||||
func writeError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrInvalidGroup):
|
||||
response.BadRequest(c, "客服分组信息不正确")
|
||||
|
||||
@@ -128,6 +128,7 @@ func currentAdminID(c *gin.Context) (uint64, bool) {
|
||||
}
|
||||
|
||||
func writeConfigError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -129,6 +129,7 @@ func currentUserID(c *gin.Context) (uint64, bool) {
|
||||
}
|
||||
|
||||
func writeWalletError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch {
|
||||
case errors.Is(err, ErrDependencyUnavailable):
|
||||
response.ServiceUnavailable(c, "数据库未连接")
|
||||
|
||||
@@ -217,6 +217,7 @@ func parseID(c *gin.Context) (uint64, bool) {
|
||||
}
|
||||
|
||||
func writeError(c *gin.Context, err error) {
|
||||
response.RecordError(c, err)
|
||||
switch err {
|
||||
case ErrWithdrawalNotFound:
|
||||
response.NotFound(c, "提现申请不存在")
|
||||
|
||||
Reference in New Issue
Block a user