重构日志与可观测性体系
新增单行文本编码器与结构化 GORM 日志,统一错误记录与请求日志策略,收紧日志文件权限并修复按天切分与压缩,支付回调参数脱敏,生产强制阿里云短信,RequestID 校验防注入,日志文案中文化。
This commit is contained in:
@@ -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])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user