Jelajahi Sumber

增加阿里云OSS签名接口

宋伯文 5 bulan lalu
induk
melakukan
6034aa935f

+ 19 - 1
desc/wechat/avatar.api

@@ -55,6 +55,20 @@ type (
         SecurityToken *string `json:"securityToken"`
         RequestId *string `json:"requestId"`
 	}
+
+	AvatarSignatureResp {
+        BaseDataInfo
+
+        // Sts information | Sts 数据
+        Data SignatureInfo `json:"data"`
+    }
+
+    SignatureInfo {
+        Key *string `json:"key"`
+        OSSAccessKeyId *string `json:"OSSAccessKeyId"`
+        Policy *string `json:"policy"`
+        Signature *string `json:"signature"`
+    }
 )
 
 @server(
@@ -68,7 +82,11 @@ service Wechat {
 	@handler getApiAvatarConfig
 	post /api/avatar/config (AvatarConfigReq) returns (AvatarConfigResp)
 
-	// get avatar configuration | 获取数字人配置信息
+	// get avatar configuration | 阿里云sts
     @handler getAcsResponse
     post /api/avatar/sts () returns (AvatarStsResp)
+
+    // get avatar configuration | 阿里云oss服务签名
+    @handler getSignatureResponse
+    post /api/avatar/signature () returns (AvatarSignatureResp)
 }

+ 31 - 0
internal/handler/avatar/get_signature_response_handler.go

@@ -0,0 +1,31 @@
+package avatar
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/avatar"
+	"wechat-api/internal/svc"
+)
+
+// swagger:route post /api/avatar/signature avatar GetSignatureResponse
+//
+// get avatar configuration | 阿里云oss服务签名
+//
+// get avatar configuration | 阿里云oss服务签名
+//
+// Responses:
+//  200: AvatarSignatureResp
+
+func GetSignatureResponseHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		l := avatar.NewGetSignatureResponseLogic(r.Context(), svcCtx)
+		resp, err := l.GetSignatureResponse()
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 17 - 16
internal/handler/routes.go

@@ -1285,21 +1285,22 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 	)
 
 	server.AddRoutes(
-		rest.WithMiddlewares(
-			[]rest.Middleware{serverCtx.Miniprogram},
-			[]rest.Route{
-				{
-					Method:  http.MethodPost,
-					Path:    "/api/avatar/config",
-					Handler: avatar.GetApiAvatarConfigHandler(serverCtx),
-				},
-				{
-					Method:  http.MethodPost,
-					Path:    "/api/avatar/sts",
-					Handler: avatar.GetAcsResponseHandler(serverCtx),
-				},
-			}...,
-		),
-		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+		[]rest.Route{
+			{
+				Method:  http.MethodPost,
+				Path:    "/api/avatar/config",
+				Handler: avatar.GetApiAvatarConfigHandler(serverCtx),
+			},
+			{
+				Method:  http.MethodPost,
+				Path:    "/api/avatar/sts",
+				Handler: avatar.GetAcsResponseHandler(serverCtx),
+			},
+			{
+				Method:  http.MethodPost,
+				Path:    "/api/avatar/signature",
+				Handler: avatar.GetSignatureResponseHandler(serverCtx),
+			},
+		},
 	)
 }

+ 107 - 0
internal/logic/avatar/get_signature_response_logic.go

@@ -0,0 +1,107 @@
+package avatar
+
+import (
+	"context"
+	"crypto/hmac"
+	"crypto/sha1"
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"time"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetSignatureResponseLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetSignatureResponseLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSignatureResponseLogic {
+	return &GetSignatureResponseLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GetSignatureResponseLogic) GetSignatureResponse() (resp *types.AvatarSignatureResp, err error) {
+	userId := l.ctx.Value("userId").(uint64)
+	helper := NewMpUploadOssHelper(l.svcCtx.Config.Aliyun.ACCESS_KEY_ID, l.svcCtx.Config.Aliyun.ACCESS_KEY_SECRET, 1, 10)
+	params := helper.CreateUploadParams()
+	OSSAccessKeyId := params["OSSAccessKeyId"]
+	policy := params["policy"]
+	signature := params["signature"]
+	key := fmt.Sprintf("mini_program/qingmasiyuai/avatar/%d.jpg", userId)
+	return &types.AvatarSignatureResp{
+		BaseDataInfo: types.BaseDataInfo{
+			Code: 0,
+			Msg:  errormsg.Success,
+		},
+		Data: types.SignatureInfo{
+			Key:            &key,
+			OSSAccessKeyId: &OSSAccessKeyId,
+			Policy:         &policy,
+			Signature:      &signature,
+		},
+	}, nil
+}
+
+type MpUploadOssHelper struct {
+	AccessKeyId     string
+	AccessKeySecret string
+	Timeout         int
+	MaxSize         int
+}
+
+type Policy struct {
+	Expiration string          `json:"expiration"`
+	Conditions [][]interface{} `json:"conditions"`
+}
+
+func NewMpUploadOssHelper(accessKeyId, accessKeySecret string, timeout, maxSize int) *MpUploadOssHelper {
+	if timeout == 0 {
+		timeout = 1
+	}
+	if maxSize == 0 {
+		maxSize = 10
+	}
+	return &MpUploadOssHelper{
+		AccessKeyId:     accessKeyId,
+		AccessKeySecret: accessKeySecret,
+		Timeout:         timeout,
+		MaxSize:         maxSize,
+	}
+}
+
+func (helper *MpUploadOssHelper) CreateUploadParams() map[string]string {
+	policy := helper.getPolicyBase64()
+	signature := helper.signature(policy)
+	return map[string]string{
+		"OSSAccessKeyId": helper.AccessKeyId,
+		"policy":         policy,
+		"signature":      signature,
+	}
+}
+
+func (helper *MpUploadOssHelper) getPolicyBase64() string {
+	expiration := time.Now().Add(time.Duration(helper.Timeout) * time.Hour).UTC().Format(time.RFC3339)
+	policy := Policy{
+		Expiration: expiration,
+		Conditions: [][]interface{}{
+			{"content-length-range", 0, helper.MaxSize * 1024 * 1024},
+		},
+	}
+	policyBytes, _ := json.Marshal(policy)
+	return base64.StdEncoding.EncodeToString(policyBytes)
+}
+
+func (helper *MpUploadOssHelper) signature(policy string) string {
+	h := hmac.New(sha1.New, []byte(helper.AccessKeySecret))
+	h.Write([]byte(policy))
+	return base64.StdEncoding.EncodeToString(h.Sum(nil))
+}

+ 15 - 0
internal/types/types.go

@@ -2507,3 +2507,18 @@ type StsInfo struct {
 	SecurityToken   *string `json:"securityToken"`
 	RequestId       *string `json:"requestId"`
 }
+
+// swagger:model AvatarSignatureResp
+type AvatarSignatureResp struct {
+	BaseDataInfo
+	// Sts information | Sts 数据
+	Data SignatureInfo `json:"data"`
+}
+
+// swagger:model SignatureInfo
+type SignatureInfo struct {
+	Key            *string `json:"key"`
+	OSSAccessKeyId *string `json:"OSSAccessKeyId"`
+	Policy         *string `json:"policy"`
+	Signature      *string `json:"signature"`
+}