fix(withdrawal): 修复提现详情收款二维码使用公网URL导致鉴权失败加载错误

- backend: withdrawal presenter 增加 privateCertificateURLs 兼容转换历史公网 payment-cert 路径
- frontend: AuthImage 与 fetchFileBlobByURL 兼容私有凭证 key,后台上下文通过管理员私有对象接口安全加载
- frontend: 按对象接口路径与 key 前缀精确判定,避免外链带 ?key= 被误代理到后台私有对象接口
- tests: 补充 TestPrivateCertificateURLs 单元测试
This commit is contained in:
yml2213
2026-09-16 14:39:32 +08:00
parent 3465475756
commit 5f5a57b81f
4 changed files with 57 additions and 6 deletions
@@ -39,3 +39,20 @@ func TestReviewWithdrawalRequestBindMissingApproved(t *testing.T) {
t.Fatal("缺少 approved 字段时应该参数绑定失败")
}
}
func TestPrivateCertificateURLs(t *testing.T) {
values := privateCertificateURLs([]string{
"/api/public/files/object?key=payment-cert%2F2026%2F09%2F16%2Fqr.webp",
"/api/public/files/object?key=avatar%2Fuser.jpg",
"/api/files/object?key=payment-cert%2Falready_private.webp",
})
if values[0] != "/api/files/object?key=payment-cert%2F2026%2F09%2F16%2Fqr.webp" {
t.Fatalf("expected private URL for payment-cert, got %q", values[0])
}
if values[1] != "/api/public/files/object?key=avatar%2Fuser.jpg" {
t.Fatalf("non-payment-cert URL should not be changed, got %q", values[1])
}
if values[2] != "/api/files/object?key=payment-cert%2Falready_private.webp" {
t.Fatalf("already private URL should not be changed, got %q", values[2])
}
}
@@ -3,6 +3,8 @@ package withdrawal
import (
"context"
"encoding/json"
"net/url"
"strings"
"hfb_sys/backend/internal/model"
)
@@ -72,6 +74,7 @@ func (r *Repository) toDetailDTO(ctx context.Context, w model.WithdrawalRequest)
if paymentAccount.CertificateURLs != nil {
json.Unmarshal(paymentAccount.CertificateURLs, &certificateURLs)
}
certificateURLs = privateCertificateURLs(certificateURLs)
}
}
@@ -118,4 +121,18 @@ func (r *Repository) toDetailDTO(ctx context.Context, w model.WithdrawalRequest)
}, nil
}
// 生成提现单号
// privateCertificateURLs 兼容历史公开收款凭证 URL,统一经私有对象接口读取。
func privateCertificateURLs(values []string) []string {
for index, value := range values {
parsed, err := url.Parse(value)
if err != nil || parsed.Path != "/api/public/files/object" {
continue
}
if !strings.HasPrefix(parsed.Query().Get("key"), "payment-cert/") {
continue
}
parsed.Path = "/api/files/object"
values[index] = parsed.String()
}
return values
}