f
This commit is contained in:
@@ -16,6 +16,8 @@ import (
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -38,6 +40,8 @@ const (
|
||||
headerOrderCode = "X-ORDER-CODE"
|
||||
headerSecretIDHdr = "secretId"
|
||||
headerAESKeyHdr = "aesKey"
|
||||
|
||||
defaultAuthPDFStorageDir = "storage/huibo-auth-pdf"
|
||||
)
|
||||
|
||||
// 汇博常见状态码
|
||||
@@ -362,6 +366,66 @@ func decodeAndValidatePDF(base64PDF string) ([]byte, error) {
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
// SaveAuthPDFLocally 解码校验后将授权 PDF 留存到本地(CallAPI2 等 JSON 接口仅留存,不上传汇博)
|
||||
func (s *HuiboService) SaveAuthPDFLocally(ctx context.Context, apiCode, authPDFBase64, subjectKey string) (string, error) {
|
||||
pdfBytes, err := decodeAndValidatePDF(authPDFBase64)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
transactionID := "unknown_tx"
|
||||
if v, ok := ctx.Value("transaction_id").(string); ok && strings.TrimSpace(v) != "" {
|
||||
transactionID = strings.TrimSpace(v)
|
||||
}
|
||||
|
||||
dir := filepath.Join(defaultAuthPDFStorageDir, strings.TrimSpace(apiCode))
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return "", fmt.Errorf("创建授权PDF存储目录失败: %w", err)
|
||||
}
|
||||
|
||||
filename := fmt.Sprintf("%s_%s_%s.pdf",
|
||||
sanitizeAuthPDFFilenamePart(transactionID),
|
||||
sanitizeAuthPDFFilenamePart(subjectKey),
|
||||
time.Now().Format("20060102_150405"),
|
||||
)
|
||||
fullPath := filepath.Join(dir, filename)
|
||||
if err := os.WriteFile(fullPath, pdfBytes, 0644); err != nil {
|
||||
return "", fmt.Errorf("写入授权PDF失败: %w", err)
|
||||
}
|
||||
|
||||
if s.logger != nil {
|
||||
s.logger.LogInfo(
|
||||
"汇博授权PDF已本地留存",
|
||||
zap.String("api_code", apiCode),
|
||||
zap.String("transaction_id", transactionID),
|
||||
zap.String("path", fullPath),
|
||||
zap.Int("size_bytes", len(pdfBytes)),
|
||||
)
|
||||
}
|
||||
return fullPath, nil
|
||||
}
|
||||
|
||||
func sanitizeAuthPDFFilenamePart(s string) string {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
return "unknown"
|
||||
}
|
||||
var b strings.Builder
|
||||
for _, r := range s {
|
||||
switch {
|
||||
case r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r >= '0' && r <= '9', r == '-', r == '_':
|
||||
b.WriteRune(r)
|
||||
default:
|
||||
b.WriteRune('_')
|
||||
}
|
||||
}
|
||||
result := b.String()
|
||||
if len(result) > 48 {
|
||||
result = result[:48]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func generateSortedParam(m map[string]string) string {
|
||||
keys := make([]string, 0, len(m))
|
||||
for k, v := range m {
|
||||
|
||||
Reference in New Issue
Block a user