jimmyyem 5 ماه پیش
والد
کامیت
cafda9f5b5

+ 1 - 1
desc/wechat/avatar.api

@@ -17,7 +17,7 @@ type (
 		UserId *string `json:"userId"`
 		AppId *string `json:"appId"`
 		UserInfoInChannel *string `json:"userInfoInChannel"`
-		Gslb []string `json:"gslb"`
+		Gslb []*string `json:"gslb"`
 	}
 
 	// start avatar request | 启动数字人

+ 3 - 1
desc/wechat/user.api

@@ -116,7 +116,9 @@ service Wechat {
 }
 
 @server(
-    group: User
+	jwt: Auth
+	group: User
+	middleware: Authority
 )
 
 service Wechat {

+ 3 - 0
desc/wechat/wx_card.api

@@ -47,6 +47,9 @@ type (
 
         // 个人介绍 
         Intro  *string `json:"intro,optional"`
+	
+		ShowChat *bool `json:"showChat"`
+		ShowAi *bool `json:"showAi"`
     }
 
 	WxCardSimpleInfo {

+ 8 - 0
hook/aliyun/aitypes.go

@@ -0,0 +1,8 @@
+package aliyun
+
+type AiTypes struct {
+	AiType          uint64 `json:"ai_type"`
+	Ak              string `json:"ak,omitempty,optional"`
+	Sk              string `json:"sk,omitempty,optional"`
+	SubscriptionKey string `json:"subscription_key,omitempty,optional"`
+}

+ 17 - 10
hook/aliyun/client.go

@@ -8,21 +8,21 @@ import (
 	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
 	util "github.com/alibabacloud-go/tea-utils/v2/service"
 	"github.com/alibabacloud-go/tea/tea"
-	"os"
 	"strings"
+	"wechat-api/internal/utils/jwt"
 )
 
 // CreateClient 使用AK&SK初始化账号Client
 // @return Client
 // @throws Exception
-func CreateClient() (_result *avatar20220130.Client, _err error) {
+func CreateClient(accessKeyId, accessKeySecret string) (_result *avatar20220130.Client, _err error) {
 	// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
 	// 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378661.html。
 	config := &openapi.Config{
 		// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
-		AccessKeyId: tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")),
+		AccessKeyId: tea.String(accessKeyId),
 		// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
-		AccessKeySecret: tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")),
+		AccessKeySecret: tea.String(accessKeySecret),
 	}
 
 	// Endpoint 请参考 https://api.aliyun.com/product/avatar
@@ -32,15 +32,18 @@ func CreateClient() (_result *avatar20220130.Client, _err error) {
 	return _result, _err
 }
 
-// userId=23423 bizId=xxxxxxx
-func startInstance(userId, bizId string) (*avatar20220130.StartInstanceResponseBodyData, error) {
-	client, _err := CreateClient()
+// StartInstance 启动数字人 userId=1234 bizId=xxoo
+func StartInstance(userId, bizId string) (*avatar20220130.StartInstanceResponseBodyData, error) {
+	accessKeyId := "LTAI5tET2mMQVTcMDftuM8Cp"
+	accessKeySecret := "AmGsD8VzwEuj8njZpUCUYnK7uUBTJa"
+	tenantId := int64(1317798064750399)
+	appId := "3dj6714h14"
+
+	client, _err := CreateClient(accessKeyId, accessKeySecret)
 	if _err != nil {
 		return nil, _err
 	}
 
-	tenantId := int64(9185)
-	appId := "ALIPUB5748B17121450"
 	startInstanceRequest := &avatar20220130.StartInstanceRequest{
 		TenantId: tea.Int64(tenantId),
 		App: &avatar20220130.StartInstanceRequestApp{
@@ -64,7 +67,7 @@ func startInstance(userId, bizId string) (*avatar20220130.StartInstanceResponseB
 }
 
 func _main(args []*string) (_err error) {
-	client, _err := CreateClient()
+	client, _err := CreateClient("", "")
 	if _err != nil {
 		return _err
 	}
@@ -115,6 +118,10 @@ func _main(args []*string) (_err error) {
 	return _err
 }
 
+func GetBizID(userId uint64) string {
+	return jwt.HashidsEncode(int(userId))
+}
+
 //func main() {
 //	err := _main(tea.StringSlice(os.Args[1:]))
 //	if err != nil {

+ 0 - 8
hook/dify/chat.go

@@ -32,11 +32,3 @@ type Metadata struct {
 func GetChatUrl() string {
 	return "/chat-messages"
 }
-
-func GetBaseUrl() string {
-	return "https://dify.gkscrm.com/v1"
-}
-
-func GetChatToken() string {
-	return "app-NhSN24G0AQV804gWtPfDnFZx"
-}

+ 11 - 7
internal/handler/routes.go

@@ -634,13 +634,17 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 	)
 
 	server.AddRoutes(
-		[]rest.Route{
-			{
-				Method:  http.MethodGet,
-				Path:    "/user/info",
-				Handler: User.GetUserInfoHandler(serverCtx),
-			},
-		},
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodGet,
+					Path:    "/user/info",
+					Handler: User.GetUserInfoHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
 	)
 
 	server.AddRoutes(

+ 57 - 1
internal/logic/avatar/get_api_avatar_config_logic.go

@@ -2,6 +2,14 @@ package avatar
 
 import (
 	"context"
+	"encoding/json"
+	avatar20220130 "github.com/alibabacloud-go/avatar-20220130/v2/client"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/zeromicro/go-zero/core/errorx"
+	"strconv"
+	"wechat-api/ent/wxcard"
+	"wechat-api/hook/aliyun"
+	"wechat-api/internal/utils/dberrorhandler"
 
 	"wechat-api/internal/svc"
 	"wechat-api/internal/types"
@@ -23,6 +31,54 @@ func NewGetApiAvatarConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext)
 }
 
 func (l *GetApiAvatarConfigLogic) GetApiAvatarConfig(req *types.AvatarConfigReq) (*types.AvatarConfigResp, error) {
+	userId := l.ctx.Value("userId").(uint64)
 
-	return &types.AvatarConfigResp{}, nil
+	card, err := l.svcCtx.DB.WxCard.Query().Where(wxcard.ID(*req.CardId)).Only(l.ctx)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	if card.AiInfo == "" {
+		return nil, errorx.NewInvalidArgumentError("AiInfo is empty")
+	}
+
+	var jsonData aliyun.AiTypes
+	err = json.Unmarshal([]byte(card.AiInfo), &jsonData)
+	if err != nil {
+		return nil, errorx.NewInvalidArgumentError(err.Error())
+	}
+
+	var aiData *avatar20220130.StartInstanceResponseBodyData
+	if jsonData.AiType == 1 { //TODO 阿里云数字人
+		userIdStr := strconv.Itoa(int(userId))
+		aiData, err = aliyun.StartInstance(userIdStr, aliyun.GetBizID(userId))
+		if err != nil {
+			return nil, errorx.NewInternalError(err.Error())
+		}
+	} else if jsonData.AiType == 2 { //TODO 小冰
+
+	}
+
+	return &types.AvatarConfigResp{
+		BaseDataInfo: types.BaseDataInfo{
+			Code: 0,
+			Msg:  errormsg.Success,
+		},
+		Data: types.AvatarInfo{
+			RequestId: aiData.RequestId,
+			SessionId: aiData.SessionId,
+			Token:     aiData.Token,
+			Channel: types.Channel{
+				ChannelId:         aiData.Channel.ChannelId,
+				Token:             aiData.Channel.Token,
+				Type:              aiData.Channel.Type,
+				ExpiredTime:       aiData.Channel.ExpiredTime,
+				Nonce:             aiData.Channel.Nonce,
+				UserId:            aiData.Channel.UserId,
+				AppId:             aiData.Channel.AppId,
+				UserInfoInChannel: aiData.Channel.UserInfoInChannel,
+				Gslb:              aiData.Channel.Gslb,
+			},
+		},
+	}, nil
 }

+ 19 - 8
internal/logic/chatrecords/submit_api_chat_logic.go

@@ -12,6 +12,8 @@ import (
 	"strconv"
 	"strings"
 	"time"
+	"wechat-api/ent/employee"
+	"wechat-api/ent/wxcard"
 	"wechat-api/ent/wxcarduser"
 	"wechat-api/hook/dify"
 	"wechat-api/hook/fastgpt"
@@ -84,14 +86,22 @@ func (l *SubmitApiChatLogic) SubmitApiChat(req *types.ChatRecordsInfo, w http.Re
 	}
 
 	if *req.BotType == 2 { // 从FastGPT里获取回答
-		fastgptSendChat(l, w, *req.Content, sessionId, userId)
+		card, err := l.svcCtx.DB.WxCard.Query().Where(wxcard.ID(*req.BotId)).Only(l.ctx)
+		if err != nil {
+			return //TODO 这里应该报错
+		}
+		fastgptSendChat(l, w, *req.Content, card.APIBase, card.APIKey, sessionId, userId)
 	} else if *req.BotType == 3 { // 从数字员工里获取回答
-		difySendChat(l, w, *req.Content, sessionId, userId)
+		employee, err := l.svcCtx.DB.Employee.Query().Where(employee.ID(*req.BotId)).Only(l.ctx)
+		if err != nil {
+			return //TODO 这里应该报错
+		}
+		difySendChat(l, w, *req.Content, employee.APIBase, employee.APIKey, sessionId, userId)
 	}
 }
 
 // fastgptSendChat 往 FastGPT 发送内容并获得响应信息
-func fastgptSendChat(l *SubmitApiChatLogic, w http.ResponseWriter, content string, sessionId, userId uint64) {
+func fastgptSendChat(l *SubmitApiChatLogic, w http.ResponseWriter, content, apiBase, apiKey string, sessionId, userId uint64) {
 	userInfo, _ := l.svcCtx.DB.WxCardUser.Query().Where(wxcarduser.ID(userId)).First(l.ctx)
 
 	var chatReq fastgpt.ChatReq
@@ -113,7 +123,8 @@ func fastgptSendChat(l *SubmitApiChatLogic, w http.ResponseWriter, content strin
 	fmt.Printf("request data:%v\n", string(jsonData))
 
 	// 建立HTTP請求
-	url := fastgpt.GetBaseUrl() + fastgpt.GetChatUrl() // 替換為正確的FastGPT API端點
+	url := apiBase + fastgpt.GetChatUrl()
+	fmt.Printf("url=%v token=%v\n", url, apiKey)
 	request, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
 	if err != nil {
 		fmt.Printf("Error creating request:%v", err)
@@ -122,7 +133,7 @@ func fastgptSendChat(l *SubmitApiChatLogic, w http.ResponseWriter, content strin
 
 	// 設置請求頭
 	request.Header.Set("Content-Type", "application/json")
-	request.Header.Set("Authorization", "Bearer "+fastgpt.GetChatToken())
+	request.Header.Set("Authorization", "Bearer "+apiKey)
 	request.Header.Set("Transfer-Encoding", "chunked")
 
 	// 發送請求
@@ -182,7 +193,7 @@ func fastgptSendChat(l *SubmitApiChatLogic, w http.ResponseWriter, content strin
 }
 
 // difySendChat 往 Dify 发送内容并获得响应信息
-func difySendChat(l *SubmitApiChatLogic, w http.ResponseWriter, content string, sessionId, userId uint64) {
+func difySendChat(l *SubmitApiChatLogic, w http.ResponseWriter, content, apiBase, apiKey string, sessionId, userId uint64) {
 	userInfo, _ := l.svcCtx.DB.WxCardUser.Query().Where(wxcarduser.ID(userId)).First(l.ctx)
 
 	var chatReq dify.ChatReq
@@ -200,7 +211,7 @@ func difySendChat(l *SubmitApiChatLogic, w http.ResponseWriter, content string,
 	fmt.Printf("request data:%v\n", string(jsonData))
 
 	// 建立HTTP請求
-	url := dify.GetBaseUrl() + dify.GetChatUrl() // 替換為正確的FastGPT API端點
+	url := apiBase + dify.GetChatUrl() // 替換為正確的FastGPT API端點
 	request, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
 	if err != nil {
 		fmt.Printf("Error creating request:%v", err)
@@ -209,7 +220,7 @@ func difySendChat(l *SubmitApiChatLogic, w http.ResponseWriter, content string,
 
 	// 設置請求頭
 	request.Header.Set("Content-Type", "application/json")
-	request.Header.Set("Authorization", "Bearer "+dify.GetChatToken())
+	request.Header.Set("Authorization", "Bearer "+apiKey)
 	request.Header.Set("Transfer-Encoding", "chunked")
 
 	// 發送請求

+ 10 - 0
internal/logic/wxcard/get_api_wx_card_detail_logic.go

@@ -37,6 +37,14 @@ func (l *GetApiWxCardDetailLogic) GetApiWxCardDetail(req *types.IDReq) (*types.W
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
+	var showChat, showAi bool
+	if data.APIKey != "" && data.APIBase != "" {
+		showChat = true
+	}
+	if data.AiInfo != "" {
+		showAi = true
+	}
+
 	return &types.WxCardInfoResp{
 		BaseDataInfo: types.BaseDataInfo{
 			Code: 0,
@@ -58,6 +66,8 @@ func (l *GetApiWxCardDetailLogic) GetApiWxCardDetail(req *types.IDReq) (*types.W
 			WechatAccount:   &data.WechatAccount,
 			Email:           &data.Email,
 			Intro:           &data.Intro,
+			ShowChat:        &showChat,
+			ShowAi:          &showAi,
 		},
 	}, nil
 }

+ 12 - 10
internal/types/types.go

@@ -2253,7 +2253,9 @@ type WxCardInfo struct {
 	// AI信息
 	AiInfo *string `json:"aiInfo,optional"`
 	// 个人介绍
-	Intro *string `json:"intro,optional"`
+	Intro    *string `json:"intro,optional"`
+	ShowChat *bool   `json:"showChat"`
+	ShowAi   *bool   `json:"showAi"`
 }
 
 // swagger:model WxCardSimpleInfo
@@ -2421,15 +2423,15 @@ type AvatarInfo struct {
 }
 
 type Channel struct {
-	ChannelId         *string  `json:"channelId"`
-	Token             *string  `json:"token"`
-	Type              *string  `json:"type"`
-	ExpiredTime       *string  `json:"expiredTime"`
-	Nonce             *string  `json:"nonce"`
-	UserId            *string  `json:"userId"`
-	AppId             *string  `json:"appId"`
-	UserInfoInChannel *string  `json:"userInfoInChannel"`
-	Gslb              []string `json:"gslb"`
+	ChannelId         *string   `json:"channelId"`
+	Token             *string   `json:"token"`
+	Type              *string   `json:"type"`
+	ExpiredTime       *string   `json:"expiredTime"`
+	Nonce             *string   `json:"nonce"`
+	UserId            *string   `json:"userId"`
+	AppId             *string   `json:"appId"`
+	UserInfoInChannel *string   `json:"userInfoInChannel"`
+	Gslb              []*string `json:"gslb"`
 }
 
 // start avatar request | 启动数字人