fix Authorization
This commit is contained in:
@@ -47,10 +47,15 @@ type (
|
||||
DocumentId int64 `json:"documentId" validate:"required"` // 授权书ID
|
||||
}
|
||||
|
||||
// DownloadAuthorizationDocumentByNameReq 通过文件名下载授权书请求
|
||||
DownloadAuthorizationDocumentByNameReq {
|
||||
FileName string `path:"fileName" validate:"required"` // 授权书文件名
|
||||
}
|
||||
|
||||
// DownloadAuthorizationDocumentResp 下载授权书响应
|
||||
DownloadAuthorizationDocumentResp {
|
||||
FileName string `json:"fileName"` // 文件名
|
||||
FileUrl string `json:"fileUrl"` // 文件访问URL
|
||||
FilePath string `json:"filePath"` // 文件存储路径
|
||||
}
|
||||
)
|
||||
|
||||
@@ -71,4 +76,8 @@ service main {
|
||||
// 下载授权书文件
|
||||
@handler DownloadAuthorizationDocument
|
||||
get /authorization/download/:documentId (DownloadAuthorizationDocumentReq) returns (DownloadAuthorizationDocumentResp)
|
||||
|
||||
// 通过文件名下载授权书文件
|
||||
@handler DownloadAuthorizationDocumentByName
|
||||
get /authorization/download/file/:fileName (DownloadAuthorizationDocumentByNameReq) returns (DownloadAuthorizationDocumentResp)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package authorization
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/authorization"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/common/xerr"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func DownloadAuthorizationDocumentByNameHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.DownloadAuthorizationDocumentByNameReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
result.ParamErrorResult(r, w, err)
|
||||
return
|
||||
}
|
||||
if err := validator.Validate(req); err != nil {
|
||||
result.ParamValidateErrorResult(r, w, err)
|
||||
return
|
||||
}
|
||||
l := authorization.NewDownloadAuthorizationDocumentByNameLogic(r.Context(), svcCtx)
|
||||
resp, err := l.DownloadAuthorizationDocumentByName(&req)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
httpx.WriteJson(w, http.StatusNotFound, result.Error(xerr.CUSTOM_ERROR, "授权书不存在"))
|
||||
return
|
||||
}
|
||||
result.HttpResult(r, w, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
file, openErr := os.Open(resp.FilePath)
|
||||
if openErr != nil {
|
||||
logx.Errorf("打开授权书文件失败: fileName=%s, filePath=%s, error=%v", req.FileName, resp.FilePath, openErr)
|
||||
result.HttpResult(r, w, nil, errors.New("授权书文件不存在"))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
fileInfo, statErr := file.Stat()
|
||||
if statErr != nil {
|
||||
logx.Errorf("读取授权书文件信息失败: fileName=%s, filePath=%s, error=%v", req.FileName, resp.FilePath, statErr)
|
||||
result.HttpResult(r, w, nil, errors.New("授权书文件不可用"))
|
||||
return
|
||||
}
|
||||
|
||||
escapedName := url.PathEscape(resp.FileName)
|
||||
w.Header().Set("Content-Type", "application/pdf")
|
||||
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"; filename*=UTF-8''%s", escapedName, escapedName))
|
||||
w.Header().Set("Content-Length", strconv.FormatInt(fileInfo.Size(), 10))
|
||||
|
||||
http.ServeContent(w, r, resp.FileName, fileInfo.ModTime(), file)
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,22 @@
|
||||
package authorization
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/authorization"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/common/xerr"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
@@ -25,6 +33,35 @@ func DownloadAuthorizationDocumentHandler(svcCtx *svc.ServiceContext) http.Handl
|
||||
}
|
||||
l := authorization.NewDownloadAuthorizationDocumentLogic(r.Context(), svcCtx)
|
||||
resp, err := l.DownloadAuthorizationDocument(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
httpx.WriteJson(w, http.StatusNotFound, result.Error(xerr.CUSTOM_ERROR, "授权书不存在"))
|
||||
return
|
||||
}
|
||||
result.HttpResult(r, w, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
file, openErr := os.Open(resp.FilePath)
|
||||
if openErr != nil {
|
||||
logx.Errorf("打开授权书文件失败: filePath=%s, error=%v", resp.FilePath, openErr)
|
||||
result.HttpResult(r, w, nil, errors.New("授权书文件不存在"))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
fileInfo, statErr := file.Stat()
|
||||
if statErr != nil {
|
||||
logx.Errorf("读取授权书文件信息失败: filePath=%s, error=%v", resp.FilePath, statErr)
|
||||
result.HttpResult(r, w, nil, errors.New("授权书文件不可用"))
|
||||
return
|
||||
}
|
||||
|
||||
escapedName := url.PathEscape(resp.FileName)
|
||||
w.Header().Set("Content-Type", "application/pdf")
|
||||
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"; filename*=UTF-8''%s", escapedName, escapedName))
|
||||
w.Header().Set("Content-Length", strconv.FormatInt(fileInfo.Size(), 10))
|
||||
|
||||
http.ServeContent(w, r, resp.FileName, fileInfo.ModTime(), file)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -841,6 +841,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/authorization/download/:documentId",
|
||||
Handler: authorization.DownloadAuthorizationDocumentHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/authorization/download/file/:fileName",
|
||||
Handler: authorization.DownloadAuthorizationDocumentByNameHandler(serverCtx),
|
||||
},
|
||||
},
|
||||
rest.WithPrefix("/api/v1"),
|
||||
)
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package authorization
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/globalkey"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type DownloadAuthorizationDocumentByNameLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewDownloadAuthorizationDocumentByNameLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DownloadAuthorizationDocumentByNameLogic {
|
||||
return &DownloadAuthorizationDocumentByNameLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *DownloadAuthorizationDocumentByNameLogic) DownloadAuthorizationDocumentByName(req *types.DownloadAuthorizationDocumentByNameReq) (resp *types.DownloadAuthorizationDocumentResp, err error) {
|
||||
builder := l.svcCtx.AuthorizationDocumentModel.SelectBuilder().
|
||||
Where("file_name = ?", req.FileName).
|
||||
Where("del_state = ?", globalkey.DelStateNo).
|
||||
Limit(1)
|
||||
|
||||
authDocs, err := l.svcCtx.AuthorizationDocumentModel.FindAll(l.ctx, builder, "")
|
||||
if err != nil {
|
||||
logx.Errorf("根据文件名查询授权书失败: fileName=%s, error=%v", req.FileName, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(authDocs) == 0 {
|
||||
logx.Errorf("根据文件名未找到授权书: fileName=%s", req.FileName)
|
||||
return nil, model.ErrNotFound
|
||||
}
|
||||
authDoc := authDocs[0]
|
||||
|
||||
if authDoc.Status != "active" {
|
||||
logx.Errorf("授权书状态异常: fileName=%s, status=%s", req.FileName, authDoc.Status)
|
||||
return nil, errors.New("授权书不可用")
|
||||
}
|
||||
|
||||
filePath := l.svcCtx.AuthorizationService.ResolveFilePath(authDoc.FilePath, authDoc.FileUrl)
|
||||
|
||||
resp = &types.DownloadAuthorizationDocumentResp{
|
||||
FileName: authDoc.FileName,
|
||||
FilePath: filePath,
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@@ -38,13 +38,12 @@ func (l *DownloadAuthorizationDocumentLogic) DownloadAuthorizationDocument(req *
|
||||
return nil, errors.New("授权书不可用")
|
||||
}
|
||||
|
||||
// 3. 构建完整文件URL
|
||||
fullFileURL := l.svcCtx.AuthorizationService.GetFullFileURL(authDoc.FileUrl)
|
||||
// 3. 构建响应
|
||||
filePath := l.svcCtx.AuthorizationService.ResolveFilePath(authDoc.FilePath, authDoc.FileUrl)
|
||||
|
||||
// 4. 构建响应
|
||||
resp = &types.DownloadAuthorizationDocumentResp{
|
||||
FileName: authDoc.FileName,
|
||||
FileUrl: fullFileURL,
|
||||
FilePath: filePath,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
|
||||
@@ -2,17 +2,19 @@ package queue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/pkg/lzkit/crypto"
|
||||
"tydata-server/pkg/lzkit/lzUtils"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
@@ -112,9 +114,9 @@ func (l *PaySuccessNotifyUserHandler) ProcessTask(ctx context.Context, t *asynq.
|
||||
|
||||
// 将授权书URL添加到解密数据中
|
||||
if authDoc != nil {
|
||||
// 生成完整的授权书访问URL
|
||||
fullAuthDocURL := l.svcCtx.AuthorizationService.GetFullFileURL(authDoc.FileUrl)
|
||||
userInfo["authorization_url"] = fullAuthDocURL
|
||||
// 生成授权书下载接口URL
|
||||
downloadURL := l.buildAuthorizationDownloadURL(authDoc.FileName)
|
||||
userInfo["authorization_url"] = downloadURL
|
||||
|
||||
// 重新序列化用户信息
|
||||
updatedDecryptData, marshalErr := json.Marshal(userInfo)
|
||||
@@ -132,7 +134,7 @@ func (l *PaySuccessNotifyUserHandler) ProcessTask(ctx context.Context, t *asynq.
|
||||
if updateParamsErr != nil {
|
||||
logx.Errorf("更新查询参数失败: %v", updateParamsErr)
|
||||
} else {
|
||||
logx.Infof("成功更新查询参数,包含授权书URL: %s", fullAuthDocURL)
|
||||
logx.Infof("成功更新查询参数,包含授权书URL: %s", downloadURL)
|
||||
}
|
||||
}
|
||||
decryptData = updatedDecryptData
|
||||
@@ -177,6 +179,18 @@ func (l *PaySuccessNotifyUserHandler) ProcessTask(ctx context.Context, t *asynq.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *PaySuccessNotifyUserHandler) buildAuthorizationDownloadURL(fileName string) string {
|
||||
escapedFileName := url.PathEscape(fileName)
|
||||
base := l.svcCtx.Config.Authorization.FileBaseURL
|
||||
if parsed, err := url.Parse(base); err == nil && parsed.Scheme != "" && parsed.Host != "" {
|
||||
parsed.Path = path.Join("/api/v1/authorization/download/file", escapedFileName)
|
||||
parsed.RawQuery = ""
|
||||
parsed.Fragment = ""
|
||||
return parsed.String()
|
||||
}
|
||||
return fmt.Sprintf("/api/v1/authorization/download/file/%s", escapedFileName)
|
||||
}
|
||||
|
||||
// 定义一个中间件函数
|
||||
func (l *PaySuccessNotifyUserHandler) handleError(ctx context.Context, err error, order *model.Order, query *model.Query) error {
|
||||
logx.Errorf("处理任务失败,原因: %v", err)
|
||||
|
||||
@@ -5,8 +5,10 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
"tydata-server/app/main/api/internal/config"
|
||||
"tydata-server/app/main/model"
|
||||
@@ -25,11 +27,13 @@ type AuthorizationService struct {
|
||||
|
||||
// NewAuthorizationService 创建授权书服务实例
|
||||
func NewAuthorizationService(c config.Config, authDocModel model.AuthorizationDocumentModel) *AuthorizationService {
|
||||
absStoragePath := determineStoragePath()
|
||||
|
||||
return &AuthorizationService{
|
||||
config: c,
|
||||
authDocModel: authDocModel,
|
||||
fileStoragePath: "data/authorization_docs", // 使用相对路径,兼容开发环境
|
||||
fileBaseURL: c.Authorization.FileBaseURL, // 从配置文件读取
|
||||
fileStoragePath: absStoragePath,
|
||||
fileBaseURL: c.Authorization.FileBaseURL, // 从配置文件读取
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +105,109 @@ func (s *AuthorizationService) GetFullFileURL(relativePath string) string {
|
||||
return fmt.Sprintf("%s/%s", s.fileBaseURL, relativePath)
|
||||
}
|
||||
|
||||
// ResolveFilePath 根据存储的路径信息解析出本地文件的绝对路径
|
||||
func (s *AuthorizationService) ResolveFilePath(filePath string, relativePath string) string {
|
||||
candidates := []string{}
|
||||
|
||||
cleanRelative := func(p string) string {
|
||||
p = strings.TrimPrefix(p, "/")
|
||||
p = strings.TrimPrefix(p, "\\")
|
||||
normalized := filepath.ToSlash(p)
|
||||
if strings.HasPrefix(normalized, "http://") || strings.HasPrefix(normalized, "https://") {
|
||||
if parsed, err := url.Parse(normalized); err == nil {
|
||||
normalized = filepath.ToSlash(strings.TrimPrefix(parsed.Path, "/"))
|
||||
}
|
||||
}
|
||||
normalized = strings.TrimPrefix(normalized, "data/authorization_docs/")
|
||||
normalized = strings.TrimPrefix(normalized, "authorization_docs/")
|
||||
normalized = strings.TrimPrefix(normalized, "./")
|
||||
normalized = strings.TrimPrefix(normalized, "../")
|
||||
return normalized
|
||||
}
|
||||
|
||||
if filePath != "" {
|
||||
candidates = append(candidates, filePath)
|
||||
}
|
||||
if relativePath != "" {
|
||||
candidates = append(candidates, filepath.Join(s.fileStoragePath, filepath.FromSlash(cleanRelative(relativePath))))
|
||||
}
|
||||
if filePath != "" {
|
||||
cleaned := filepath.Clean(filePath)
|
||||
if strings.HasPrefix(cleaned, s.fileStoragePath) {
|
||||
candidates = append(candidates, cleaned)
|
||||
} else {
|
||||
trimmed := strings.TrimPrefix(cleaned, "data"+string(os.PathSeparator)+"authorization_docs"+string(os.PathSeparator))
|
||||
trimmed = strings.TrimPrefix(trimmed, "data/authorization_docs/")
|
||||
if trimmed != cleaned {
|
||||
candidates = append(candidates, filepath.Join(s.fileStoragePath, filepath.FromSlash(cleanRelative(trimmed))))
|
||||
}
|
||||
if !filepath.IsAbs(cleaned) {
|
||||
candidates = append(candidates, filepath.Join(s.fileStoragePath, filepath.FromSlash(cleanRelative(cleaned))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, candidate := range candidates {
|
||||
if candidate == "" {
|
||||
continue
|
||||
}
|
||||
pathCandidate := candidate
|
||||
if !filepath.IsAbs(pathCandidate) {
|
||||
if absPath, err := filepath.Abs(pathCandidate); err == nil {
|
||||
pathCandidate = absPath
|
||||
}
|
||||
}
|
||||
if statErr := checkFileExists(pathCandidate); statErr == nil {
|
||||
return pathCandidate
|
||||
}
|
||||
}
|
||||
|
||||
logx.Errorf("授权书文件路径解析失败 filePath=%s fileUrl=%s candidates=%v", filePath, relativePath, candidates)
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func determineStoragePath() string {
|
||||
candidatePaths := []string{
|
||||
"data/authorization_docs",
|
||||
"../data/authorization_docs",
|
||||
"../../data/authorization_docs",
|
||||
"../../../data/authorization_docs",
|
||||
}
|
||||
|
||||
for _, candidate := range candidatePaths {
|
||||
absPath, err := filepath.Abs(candidate)
|
||||
if err != nil {
|
||||
logx.Errorf("解析授权书存储路径失败: %s, err=%v", candidate, err)
|
||||
continue
|
||||
}
|
||||
if info, err := os.Stat(absPath); err == nil && info.IsDir() {
|
||||
logx.Infof("授权书存储路径选择: %s", absPath)
|
||||
return absPath
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有现成的目录,使用第一个候选的绝对路径
|
||||
absPath, err := filepath.Abs(candidatePaths[0])
|
||||
if err != nil {
|
||||
logx.Errorf("解析默认授权书存储路径失败,使用相对路径: %s, err=%v", candidatePaths[0], err)
|
||||
return candidatePaths[0]
|
||||
}
|
||||
logx.Infof("授权书存储路径创建: %s", absPath)
|
||||
return absPath
|
||||
}
|
||||
|
||||
func checkFileExists(path string) error {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
return fmt.Errorf("path %s is directory", path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// generatePDFContent 生成PDF内容
|
||||
func (s *AuthorizationService) generatePDFContent(userInfo map[string]interface{}) ([]byte, error) {
|
||||
// 创建PDF文档
|
||||
@@ -113,7 +220,7 @@ func (s *AuthorizationService) generatePDFContent(userInfo map[string]interface{
|
||||
"/app/static/SIMHEI.TTF", // Docker容器内的字体文件
|
||||
"app/main/api/static/SIMHEI.TTF", // 开发环境备用路径
|
||||
}
|
||||
|
||||
|
||||
// 尝试添加字体
|
||||
fontAdded := false
|
||||
for _, fontPath := range fontPaths {
|
||||
@@ -150,17 +257,17 @@ func (s *AuthorizationService) generatePDFContent(userInfo map[string]interface{
|
||||
pdf.SetFont("Arial", "", 20)
|
||||
}
|
||||
pdf.CellFormat(0, 15, "授权书", "", 1, "C", false, 0, "")
|
||||
|
||||
|
||||
// 添加空行
|
||||
pdf.Ln(5)
|
||||
|
||||
|
||||
// 设置正文样式 - 正常字体
|
||||
if fontAdded {
|
||||
pdf.SetFont("ChineseFont", "", 12)
|
||||
} else {
|
||||
pdf.SetFont("Arial", "", 12)
|
||||
}
|
||||
|
||||
|
||||
// 构建授权书内容(去掉标题部分)
|
||||
content := fmt.Sprintf(`海南天远大数据科技有限公司:
|
||||
本人%s拟向贵司申请大数据分析报告查询业务,贵司需要了解本人相关状况,用于查询大数据分析报告,因此本人同意向贵司提供本人的姓名和手机号等个人信息,并同意贵司向第三方传送上述信息。第三方将使用上述信息核实信息真实情况,查询信用记录,并生成报告。
|
||||
|
||||
@@ -1231,13 +1231,17 @@ type DirectPushReport struct {
|
||||
Last30D TimeRangeReport `json:"last30d"` // 近30天数据
|
||||
}
|
||||
|
||||
type DownloadAuthorizationDocumentByNameReq struct {
|
||||
FileName string `path:"fileName" validate:"required"` // 授权书文件名
|
||||
}
|
||||
|
||||
type DownloadAuthorizationDocumentReq struct {
|
||||
DocumentId int64 `json:"documentId" validate:"required"` // 授权书ID
|
||||
}
|
||||
|
||||
type DownloadAuthorizationDocumentResp struct {
|
||||
FileName string `json:"fileName"` // 文件名
|
||||
FileUrl string `json:"fileUrl"` // 文件访问URL
|
||||
FilePath string `json:"filePath"` // 文件存储路径
|
||||
}
|
||||
|
||||
type Feature struct {
|
||||
|
||||
@@ -32,12 +32,8 @@ func NewAuthorizationDocumentModel(conn sqlx.SqlConn, c cache.CacheConf) Authori
|
||||
// FindByOrderId 根据订单ID查询授权书列表
|
||||
func (m *customAuthorizationDocumentModel) FindByOrderId(ctx context.Context, orderId int64) ([]*AuthorizationDocument, error) {
|
||||
query := `SELECT * FROM authorization_document WHERE order_id = ? AND del_state = 0 ORDER BY create_time DESC`
|
||||
|
||||
|
||||
var authDocs []*AuthorizationDocument
|
||||
err := m.QueryRowsNoCacheCtx(ctx, &authDocs, query, orderId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return authDocs, nil
|
||||
return authDocs, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user