package service import ( "context" "encoding/json" "finclip-app-manager/domain/entity" "finclip-app-manager/domain/entity/proto" "finclip-app-manager/domain/entity/proto/apiproto" "finclip-app-manager/domain/repository" "finclip-app-manager/infrastructure/cache/redis" "finclip-app-manager/infrastructure/client/grpc" "finclip-app-manager/infrastructure/client/httpcall" "finclip-app-manager/infrastructure/config" impl "finclip-app-manager/infrastructure/db/repo" pb "finclip-app-manager/infrastructure/protobuf/golang" "finclip-app-manager/infrastructure/utility" "finclip-app-manager/infrastructure/utils" "fmt" "net/http" "github.com/gin-gonic/gin" uuid "github.com/satori/go.uuid" "gitlab.finogeeks.club/finclip-backend/apm" ) type AppAppletInfoService struct { appBuildInfoRepo repository.IAppBuildInfoRepo appRepo repository.AppRepository tempAppRepo repository.IAppTempInfoRepo qrcodeRepo repository.IQrCodeInfoRepo } func NewAppAppletInfoService() *AppAppletInfoService { return &AppAppletInfoService{ appBuildInfoRepo: impl.InitBuildInfoRepo(), appRepo: impl.InitAppRepo(), tempAppRepo: impl.InitAppTempInfoRepo(), qrcodeRepo: impl.InitQrCodeInfoRepo(), } } type GetPubVerListRspItem struct { AppID string `json:"appId" bson:"appId"` Name string `json:"name" bson:"name"` Version string `json:"version" bson:"version"` Sequence int `json:"sequence" bson:"sequence"` AppBuildID string `json:"appBuildID" bson:"appBuildID"` AppBuildInfoId string `json:"buildInfoId" bson:"buildInfoId"` PathAndQuery string `json:"pathAndQuery" bson:"pathAndQuery"` StartParams entity.AppStartParams `json:"startParams"` WechatInfo WechatInfoRsp `json:"wechatInfo" bson:"wechatInfo"` } type WechatInfoRsp struct { WechatAppSecret string `json:"wechatAppSecret" bson:"wechatAppSecret"` WechatAppId string `json:"wechatAppId" bson:"wechatAppId"` WechatPath string `json:"wechatPath" bson:"wechatPath"` WechatSize string `json:"wechatSize" bson:"wechatSize"` QrcodeUrl string `json:"qrcodeUrl" bson:"qrcodeUrl"` QrcodeDownloadUrl string `json:"qrcodeDownloadUrl" bson:"qrcodeDownloadUrl"` Updated int64 `json:"updated" bson:"updated"` ShowHint bool `json:"showHint" bson:"-"` // 是否展示提示 } func (as *AppAppletInfoService) GetAppBuilds(ctx context.Context, operatorID, appId string, pageSize, pageNo int) ([]entity.AppBuildInfo, int64, error) { groupInfo, err := hCaller.GetGroupInfoByUserId(ctx, operatorID) if err != nil { return nil, 0, err } total, res, err := as.appBuildInfoRepo.GetAppBuilds(ctx, groupInfo.GroupID, appId, pageSize, pageNo) if err != nil { log.Errorf("GetAppBuilds err:%s", err.Error()) return nil, 0, err } return res, total, nil } func (as *AppAppletInfoService) GetAppVerBuildInfos(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) appId := c.Query("appId") if appId == "" { log.Errorf("appId is empty!!!") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_LACK_OF_APPID, nil) return } app, err := as.appRepo.GetAppInfo(traceCtx, appId) if err != nil { if as.appBuildInfoRepo.NotFound(err) { utility.MakeLocRsp(c, http.StatusNotFound, utility.FS_APP_ID_NOT_FOUND, nil) return } utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, nil) return } //获取体验版信息 trialResult, err := as.appBuildInfoRepo.GetTrialInfoByAppId(traceCtx, appId) if err != nil { utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, nil) return } log.Debugf("trialResult data:", trialResult) //获取线上版信息 //publishSvr := service.NewAppVerService() publishedList, _, err := as.appRepo.GetAllPublishedVerList(traceCtx, appId) //&& !avs.appVerT.NotFound() if err != nil { log.Errorf("GetAllPublishedVerList db err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, nil) return } var pubResult []GetPubVerListRspItem for _, v := range publishedList { pubItem := GetPubVerListRspItem{} if len(v.AppBuildID) > 0 { appInfo, err := as.appBuildInfoRepo.GetInfoById(traceCtx, v.AppBuildID) if err != nil { log.Errorf("GetInfoById err:%s", err.Error()) return } else { pubItem.AppID = v.AppID pubItem.AppBuildID = v.AppBuildID //pubItem.AppBuildInfoId = appInfo.BuildInfoId pubItem.AppBuildInfoId = appInfo.Id pubItem.Sequence = v.Sequence pubItem.Version = v.Version pubItem.Name = v.Name pubItem.PathAndQuery = appInfo.StartParams.PathAndQuery } wechatInfo, err := hCaller.GetWeChatInfo(traceCtx, v.AppID) if err != nil { utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, nil) return } if wechatInfo.Updated == 0 { wechatInfo.Updated = app.PublishedStatus.LastUpdated } info := WechatInfoRsp{} info.WechatAppSecret = wechatInfo.WechatAppSecret info.WechatAppId = wechatInfo.WechatAppId info.WechatPath = wechatInfo.WechatPath info.QrcodeUrl = wechatInfo.QrcodeUrl info.QrcodeDownloadUrl = wechatInfo.QrcodeDownloadUrl info.Updated = wechatInfo.Updated info.WechatSize = wechatInfo.WechatSize pubItem.WechatInfo = info pubResult = append(pubResult, pubItem) } } log.Debugf("pubResult data:", pubResult) utility.MakeLocRsp(c, http.StatusOK, utility.OK, gin.H{"trialVer": trialResult, "pubVer": pubResult}) } func (as *AppAppletInfoService) UpdateTrialApp(ctx context.Context, userId, Id, Type, AppId string) error { groupInfo, err := hCaller.GetGroupInfoByUserId(ctx, userId) if err != nil { log.Errorf("UpdateTrialApp get user info err:%s,useid:[%s]", err.Error(), userId) return err } buildInfo, err := as.appBuildInfoRepo.GetInfoById(ctx, Id) if err != nil { log.Errorf("UpdateTrialApp get info err:%s", err.Error()) return err } if groupInfo.GroupID != buildInfo.GroupID { log.Errorf("UpdateTrialApp user group id not match info id,userId:[%s]", userId) return err } err = as.UpdateTrial(ctx, Id, Type, AppId) if err != nil { log.Errorf("UpdateTrial error:", err.Error()) return err } return nil } func (as *AppAppletInfoService) UpdateTrial(ctx context.Context, infoId, opType, appId string) error { var err error switch opType { case "add": nowTrailInfo, err := as.appBuildInfoRepo.GetTrialInfoByAppId(ctx, appId) if err != nil { if !repository.NotFound(err) { log.Errorf("get now trial info err:%s", err.Error()) return err } } else { //todo 这里需确定是否需要删除缓存 //avs.updateTrialInfoCache(ctx, "del", nowTrailInfo.Id) //取消之前的 err = as.appBuildInfoRepo.CancelTrial(ctx, nowTrailInfo.Id) if err != nil { log.Errorf("add trial before cancel trial err:%s", err.Error()) return err } } err = as.appBuildInfoRepo.AddTrial(ctx, infoId) if err != nil { log.Errorf("AppBuildService AddTrial err:%s", err.Error()) return err } //添加二维码信息 qrcodeInfo := &entity.QrCodeInfo{ Type: entity.QrCodeTypeTrial, Uuid: GenTrialQrCodeUuid(appId), AppId: appId, Sequence: 0, ApiServer: config.Cfg.ApiServer, CodeId: infoId, StartParams: entity.AppStartParams{}, CreateTime: utils.GetNowMs(), } err = as.qrcodeRepo.GenInfo(ctx, qrcodeInfo) case "cancel": //todo 这里需确定是否需要删除缓存 //as.appBuildInfoRepo.UpdateTrialInfoCache(ctx, "del", infoId) err = as.appBuildInfoRepo.CancelTrial(ctx, infoId) } if err != nil { log.Errorf("AppBuildService AddTrial err:%s", err.Error()) return err } err = hCaller.TrialQrReset(ctx, infoId) if err != nil { //utility.MakeLocRsp(http.StatusInternalServerError, utility.FS_DB_ERR) return err } return nil } func (as *AppAppletInfoService) UpdateTrialAppPathAndQueryHand(ctx context.Context, userId, TraceId, PathAndQuery string) error { groupInfo, err := hCaller.GetGroupInfoByUserId(ctx, userId) if err != nil { log.Errorf("UpdateTrialAppPathHand GetAccountInfo err:%s,userId:[%s]", err.Error(), userId) return err } trialInfo, err := as.appBuildInfoRepo.GetTrialInfoById(ctx, TraceId) if err != nil { if err.Error() == "not found" { log.Errorf("UpdateTrialAppPathHand id not trial,TraceId:%+v", TraceId) return err } log.Errorf("GetTrialInfoById err:%s", err.Error()) return err } if groupInfo.GroupID != trialInfo.GroupID { log.Errorf("req user info group id not match up info userId:%s", userId) return err } /*params := trialInfo.StartParams params.PathAndQuery = req.PathAndQuery*/ params := entity.AppStartParams{} params.PathAndQuery = PathAndQuery err = as.UpdateTrialAppStartParams(ctx, TraceId, params) if err != nil { log.Errorf("AppBuildService AddTrial err:%s", err.Error()) return err } return nil } func (as *AppAppletInfoService) UpdateTrialAppStartParams(ctx context.Context, infoId string, params entity.AppStartParams) error { log.Debugf("UpdateTrialAppStartParams info id:[%s],params:%+v", infoId, params) err := as.appBuildInfoRepo.UpdateTrialStartParams(ctx, infoId, params) if err != nil { log.Errorf("UpdateTrialAppPath db err:%s", err.Error()) return err } qrcodeSvr := NewQrCodeInfoService() err = qrcodeSvr.UpdateTrialStartParams(ctx, infoId, params) if err != nil { log.Errorf("UpdateTrialStartParams db err:%s", err.Error()) return err } //err = NewRedDotService().TrialQrReset(ctx, infoId) err = hCaller.TrialQrReset(ctx, infoId) if err != nil { //utility.MakeLocRsp(http.StatusInternalServerError, utility.FS_DB_ERR) return err } return nil } type GetTrialAppInfoRsp struct { Info interface{} `json:"info"` QrcodeHasRead bool `json:"qrcodeHasRead"` } func (as *AppAppletInfoService) GetTrialAppInfo(ctx context.Context, userId, appId string) (GetTrialAppInfoRsp, error) { rspData := GetTrialAppInfoRsp{} groupInfo, err := hCaller.GetGroupInfoByUserId(ctx, userId) if err != nil { log.Errorf("GetTrialAppInfo get user info err:%s,useid:[%s]", err.Error(), userId) return rspData, err } buildInfo, err := as.appBuildInfoRepo.GetTrialInfoByAppId(ctx, appId) if err != nil { if err.Error() != "not found" { log.Errorf("GetTrialAppInfo get info err:%s", err.Error()) return rspData, err } return rspData, err } if groupInfo.GroupID != buildInfo.GroupID { log.Errorf("GetTrialAppInfo user group id not match info id,userId:[%s]", userId) return rspData, err } qrcodeHasRead, err := hCaller.IsTrialHasRead(ctx, buildInfo.Id, userId) if err != nil { log.Errorf("TrialHasRead err:%s", err.Error()) return rspData, err } rspData.Info = buildInfo rspData.QrcodeHasRead = qrcodeHasRead return rspData, nil } func (as *AppAppletInfoService) GetInfoById(ctx context.Context, id string) (*entity.AppBuildInfo, error) { //先从缓存中取 /*infoByte, err := avs.rc.GetBytes(ctx, "mop_app_manage_build_info_"+id) if err == nil { common.GLog.Debugf("GetInfoById from redis,id:%s", id) rspInfo := new(model.AppBuild) if err = json.Unmarshal(infoByte, &rspInfo); err == nil { return rspInfo, err } }*/ info, err := as.appBuildInfoRepo.GetInfoById(ctx, id) if err != nil { log.Errorf("GetInfoById err:%s", err.Error()) if repository.NotFound(err) { return nil, entity.ErrNotFound } return nil, err } //infoByte, _ = json.Marshal(info) //avs.rc.Set(ctx, "mop_app_manage_build_info_"+id, string(infoByte), config.Cfg.RedisExpireTime) return info, nil } func (as *AppAppletInfoService) GetInfoByBuildInfoId(ctx context.Context, buildInfo string) (*entity.AppBuildInfo, error) { info, err := as.appBuildInfoRepo.GetInfoByBuildInfoId(ctx, buildInfo) if err != nil { log.Errorf("GetInfoByBuildInfoId err:%s", err.Error()) if repository.NotFound(err) { return nil, entity.ErrNotFound } return nil, err } return info, nil } func (as *AppAppletInfoService) GetManageAppList(ctx context.Context, userId, sdkKey, apiServer string) (interface{}, *utility.SvrRsp) { rsp := utility.DefaultSvrRsp() rspAppList := make([]apiproto.GetManageAppListRspDataItem, 0) sdkInWhiteList := utils.InArry(sdkKey, config.WhiteSDKArry) //白名单的特殊处理 if sdkInWhiteList { groups := make([]string, 0) /*//获取用户id对应的所有机构Id authInfo, err := hCaller.GetAuthByUserIdAndGroups(ctx, "getUserIdGroupsAndAuth", userId, []string{}) if err != nil { log.Errorf("GetManageAppList GetAuthByUserIdAndGroups err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } if !authInfo.HasAuth {*/ //是否为企业管理员 groupMap := make(map[string]string) adminInfo, err := hCaller.GetIsOrganCreator(ctx, userId) if err != nil { log.Errorf("GetManageAppList GetIsOrganAdmin err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } if adminInfo.IsCreator { groupMap[adminInfo.OrganId] = adminInfo.OrganId } /*//小程序创建者 appByCreatorInfo, err := as.appRepo.GetAppByCreator(ctx, userId) if err != nil { log.Errorf("GetManageAppList GetIsOrganCreator err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } if len(appByCreatorInfo) > 0 { for _, v := range appByCreatorInfo { groupMap[v.GroupID] = v.GroupID } }*/ //获取用户id对应的所有机构Id authInfo, err := hCaller.GetAuthByUserIdAndGroups(ctx, "getUserIdGroupsAndAuth", userId, []string{}) if err != nil { log.Errorf("GetManageAppList GetAuthByUserIdAndGroups err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } if !authInfo.HasAuth && !adminInfo.IsCreator { log.Errorf("GetAuthByUserIdAndGroups user id no auth,rsp:%+v,userId:%s", authInfo, userId) return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_MANAGE_APP_NO_AUTH) } //获取对应机构id下的所有小程序 for id, v := range authInfo.AuthList { if v.Dev || v.Trial { groupMap[id] = id } } for _, v := range groupMap { groups = append(groups, v) } total, appVers, err := as.appRepo.GetAppsByGroupIds(ctx, groups) if err != nil { log.Errorf("GetManageAppList get app ver err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } for _, info := range appVers { item := apiproto.GetManageAppListRspDataItem{AppId: info.AppID, Name: info.Name, Logo: info.Logo} rspAppList = append(rspAppList, item) } return gin.H{"total": total, "appList": rspAppList, "apiServer": apiServer}, rsp.SetLoc(http.StatusOK, utility.OK) } //首先获取sdkKey关联的所有小程序 bindInfoList, err := impl.InitBindingRepo().GetBindListBySdkKey(ctx, sdkKey) if err != nil { log.Errorf("GetManageAppList GetBindListBySdkKey err:%s", err.Error()) if !impl.InitBindingRepo().NotFound(err) { return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } else { return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_BIND_NOT_FOUND) } } appIdList := make([]string, 0) groups := make([]string, 0) for _, v := range bindInfoList { groups = append(groups, v.GroupID) } appIdMap := make(map[string]string) //userId为企业管理员 adminInfo, err := hCaller.GetIsOrganCreator(ctx, userId) if err != nil { log.Errorf("GetManageAppList GetIsOrganAdmin err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } if adminInfo.IsCreator { for _, v := range bindInfoList { if v.GroupID == adminInfo.OrganId { for _, appInfo := range v.AppInfos { //appIdList = append(appIdList, appInfo.AppID) appIdMap[appInfo.AppID] = appInfo.AppID } } } } //判断这些企业下面有没有这个userId authInfo, err := hCaller.GetAuthByUserIdAndGroups(ctx, "getUserInGroupsAuth", userId, groups) if err != nil { log.Errorf("GetManageAppList GetAuthByUserIdAndGroups err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } fmt.Println("authInfo", utility.InterfaceToJsonString(authInfo)) if !authInfo.HasAuth && !adminInfo.IsCreator { log.Errorf("GetAuthByUserIdAndGroups user id no auth,rsp:%+v,userId:%s", authInfo, userId) return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_MANAGE_APP_NO_AUTH) } for _, v := range bindInfoList { if info, ok := authInfo.AuthList[v.GroupID]; ok { if info.Dev || info.Trial { for _, appInfo := range v.AppInfos { appIdMap[appInfo.AppID] = appInfo.AppID } } } } for _, v := range appIdMap { appIdList = append(appIdList, v) } //获取所有的小程序详情 appVers, err := as.appRepo.GetAppsByAppIds(ctx, appIdList) for _, info := range appVers { item := apiproto.GetManageAppListRspDataItem{AppId: info.AppID, Name: info.Name, Logo: info.Logo} rspAppList = append(rspAppList, item) } return gin.H{"total": len(appIdList), "appList": rspAppList, "apiServer": apiServer}, rsp.SetLoc(http.StatusOK, utility.OK) } func (as *AppAppletInfoService) GetManageAppVerList(ctx context.Context, t, appId, apiServer string) (*apiproto.GetManageAppVerListRspData, *utility.SvrRsp) { rsp := utility.DefaultSvrRsp() rspData := apiproto.GetManageAppVerListRspData{} //todo 结果不是数组,只有一个 releaseInfo, err := as.appRepo.GetOnlineAppVer(ctx, appId) if err != nil { if !repository.NotFound(err) { log.Errorf("GetManageAppVerList GetPubVerInfo err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } rspData.ReleaseInfo = nil } else { rspData.ReleaseInfo = &apiproto.ManageReleaseInfo{ AppId: releaseInfo.AppID, Version: releaseInfo.Version, VersionDescription: releaseInfo.CustomData.VersionDescription, CreateBy: releaseInfo.CustomData.Developer, CreateAt: releaseInfo.Created, } if len(releaseInfo.CustomData.SourceFile) > 0 { rspData.ReleaseInfo.CreateAt = releaseInfo.CustomData.SourceFile[0].UploadDate } } trialInfo, err := as.appBuildInfoRepo.GetTrialInfoByAppId(ctx, appId) if err != nil { log.Errorf("GetManageAppVerList GetTrialInfoByAppId err:%s", err.Error()) if !repository.NotFound(err) { return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } } else { rspData.TrialInfo = &apiproto.ManageTrialInfo{ CodeId: trialInfo.Id, Version: trialInfo.Version, VersionDescription: trialInfo.CustomData.VersionDescription, CreateBy: trialInfo.CreatedBy, CreateAt: trialInfo.Created, QrcodeSign: as.getQrCodeSign(entity.BuildInfoTypeTrial, trialInfo.Id, apiServer), } } rspData.DevInfo = &apiproto.ManageDevInfo{Total: 0, List: make([]apiproto.ManageDevInfoItem, 0)} if t == "dev" { total, devList, err := as.appBuildInfoRepo.GetList(ctx, appId, 1, config.Cfg.ManageAppDevCount) if err != nil { log.Errorf("GetManageAppVerList GetList err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } rspData.DevInfo.Total = int(total) for _, v := range devList { if v.Status { rspData.DevInfo.List = append(rspData.DevInfo.List, apiproto.ManageDevInfoItem{ CodeId: v.Id, Version: v.Version, VersionDescription: v.CustomData.VersionDescription, CreateBy: v.CreatedBy, CreateAt: v.Created, QrcodeSign: as.getQrCodeSign(entity.BuildInfoTypeDevelopment, v.Id, apiServer), }) } } } rspData.ApiServer = apiServer log.Infof("GetManageAppVerList rsp:%+v", rspData) return &rspData, rsp.SetLoc(http.StatusOK, utility.OK) } func (as *AppAppletInfoService) FixDevListStatus(ctx context.Context) *utility.SvrRsp { rsp := utility.DefaultSvrRsp() result, err := as.appBuildInfoRepo.GetAll(ctx) if err != nil { log.Errorf("FixDevListStatus GetAll err:%s", err.Error()) return rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } log.Infof("FixDevListStatus total:%v", len(result)) type TempBuildInfo struct { Id string `bson:"id"` Status bool `bson:"status"` } var succTotal = 0 //todo 获取编译服务appletbuilds表数据 /*for _, v := range result { info := TempBuildInfo{} err = buildT.GetOneV2(traceCtx, bson.M{"id": v.BuildInfoId}, &info) if err != nil { log.Errorf("buildT GetOneV2 err:%s", err.Error()) } else { err = t.UpdateOne(traceCtx, bson.M{"id": v.Id}, bson.M{"$set": bson.M{"status": info.Status}}) if err != nil { log.Errorf("UpdateOne err:%s", err.Error()) } else { succTotal += 1 } } log.Infof("update info:%+v,info:%+v", v, info) //break }*/ for _, v := range result { result, err := hCaller.GetAppletInfoById(ctx, v.BuildInfoId) if err != nil { log.Errorf("buildT GetOneV2 err:%s", err.Error()) } else { err = as.appBuildInfoRepo.UpdateOneStatus(ctx, v.Id, result.Status) if err != nil { log.Errorf("UpdateOne err:%s", err.Error()) } else { succTotal += 1 } } log.Infof("update info:%+v,info:%+v", v, result) } log.Infof("FixDevListStatus total:%d,success total:%d", len(result), succTotal) return rsp.SetLoc(http.StatusOK, utility.OK) } /*func (as *AppAppletInfoService) GetBuildInfo(ctx context.Context, req apiproto.GetBuildAppInfoReq, sdkKey string) (*pb.BuildAppInfo, *utility.SvrRsp) { switch req.Type { case entity.BuildInfoTypeTrial: //获取体验版小程序详情 return as.GetTrialInfo(ctx, req.CodeId, sdkKey) case entity.BuildInfoTypeTemporary: //获取ide临时小程序详情 return as.getTempAppInfo(ctx, req.CodeId) case entity.BuildInfoTypeDevelopment: return as.GetDevInfo(ctx, req.CodeId, sdkKey) default: return nil, utility.DefaultSvrRsp().SetLoc(http.StatusBadRequest, utility.FS_PARAM_ERR) } }*/ func (as *AppAppletInfoService) DevGetTrialInfo(ctx context.Context, appId string) (*entity.AppBuildInfo, error) { info, err := as.appBuildInfoRepo.GetTrialInfoByAppId(ctx, appId) if as.appBuildInfoRepo.NotFound(err) { log.Debugln("DevGetTrialInfo not found !") return info, entity.NotFoundErr } return info, err } func (as *AppAppletInfoService) GetTrialInfo(ctx context.Context, codeId, sdkKey string) (*pb.BuildAppInfo, *utility.SvrRsp) { buildInfo := new(pb.BuildAppInfo) rsp := utility.DefaultSvrRsp() /*buildInfoCacheByte, err := avs.rc.GetBytes(ctx, avs.getTrialInfoCacheKey(codeId)) if err == nil { if err = json.Unmarshal(buildInfoCacheByte, buildInfo); err == nil { log.Infof("GetTrialInfo from cache ...") return buildInfo, nil } }*/ info, err := as.appBuildInfoRepo.GetInfoById(ctx, codeId) if err != nil { log.Errorf("GetTrialInfo get info err:%s", err.Error()) if as.appBuildInfoRepo.NotFound(err) { return buildInfo, rsp.SetLoc(http.StatusNotFound, utility.FS_NOT_FOUND) } return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_DB_ERR) } if info.Source != entity.APP_BUILD_SOURCE_TRIAL { log.Infoln("GetTrialInfo id is not a trial info:[%s]", codeId) return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_NOT_TRIAL_INFO) } appVerInfo, err := as.appRepo.GetAppVerInfo(ctx, info.AppID, 0) if err != nil { log.Errorf("GetTrialInfo GetAppVerInfo err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_DB_ERR) } groupInfo, err := hCaller.GetGroupInfoByUserId(ctx, appVerInfo.GroupID) if err != nil { log.Errorf("GetTrialInfo GetGroupInfoByUserId err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } // 获取开发者信息 //developerInfo, err := client.GetDeveloperInfo(ctx, appVerInfo.DeveloperID) //if err != nil { // log.Errorf("GetDeveloperInfo err:%s", err.Error()) // return nil, rsp.SetLoc(gin.H{}, http.StatusInternalServerError, common.FS_SERVER_ERR) //} //status := avs.account.getAccountStatus(groupInfo, developerInfo) if config.Cfg.IsUatEnv() { if !hCaller.UatOrganStatusIsValid(groupInfo.ReviewStatus) { log.Errorf("GetTrialInfo get info organ info invalid,code id:%s", codeId) return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_ORGAN_STATUS_INVALID) } } else { if !hCaller.OrganStatusIsValid(groupInfo.ReviewStatus) { log.Errorf("GetTrialInfo get info organ info invalid,code id:%s", codeId) return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_ORGAN_STATUS_INVALID) } } domainInfo, err := hCaller.GetAppDomainByOrganId(ctx, groupInfo.GroupID) if err != nil { log.Errorf("GetTrialInfo ger domain info err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } //支付信息过期校验 if config.Cfg.OpenPurchAuth && config.Cfg.PublishEnv == config.ENV_UAT { appStatus, err := as.CheckIdStatus(ctx, appVerInfo.AppID) if err != nil { log.Errorf("CheckIdStatus err:%s,appId:%s", err.Error(), appVerInfo.AppID) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } if appStatus == httpcall.PAY_ID_STATUS_EXPIRE { log.Errorf("check appid purch status no ok ") return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_APP_PAY_EXPIRE) } } log.Debugf("get group id:%s,sdkKey:%s", appVerInfo.GroupID, sdkKey) inWhiteList := utils.InArry(sdkKey, config.WhiteSDKArry) if !inWhiteList { repo := impl.InitBindingRepo() bindingInfo, err := repo.GetInfoBySdkKeyOrganId(ctx, appVerInfo.GroupID, sdkKey) if err != nil { log.Errorf("GetInfoBySdkKeyOrganId err:%s", err.Error()) if repo.NotFound(err) { return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_BIND_NOT_FOUND) } return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } if bindingInfo.CooperateStatus.Value != entity.StBindValid { log.Errorf("GetTrialInfo binding bind invalid,binding info:%+v", bindingInfo) return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_COOPERATION_TERMINATED) } //支付信息校验 if config.Cfg.OpenPurchAuth && config.Cfg.PublishEnv == config.ENV_UAT { bindStatus, err := as.CheckIdStatus(ctx, bindingInfo.BindingID) if err != nil { log.Errorf("CheckIdStatus err:%s,bindingId:%s", err.Error(), bindingInfo.BindingID) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } if bindStatus == httpcall.PAY_ID_STATUS_EXPIRE { log.Errorf("binding id pay check no ok ") return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_BIND_PAY_EXPIRE) } } appAssBind := false for _, v := range bindingInfo.AppInfos { if v.AppID == appVerInfo.AppID { appAssBind = true } } if !appAssBind { log.Errorf("GetTrialInfo sdk key not ass binding,appId:[%s]", appVerInfo.AppID) return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_APP_NOT_ASS_BIND) } } buildInfo.CodeId = info.Id buildInfo.CoreDescription = appVerInfo.CoreDescription buildInfo.Created = info.Created buildInfo.CreatedBy = info.CreatedBy err, errCode, customData := ConvertModelCustomDataToPb(ctx, info.GroupID, appVerInfo.CustomData, domainInfo, "cache") if err != nil { log.Errorf("ConvertModelCustomDataToPb err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, errCode) } buildInfo.CustomData = customData buildInfo.GroupId = info.GroupID buildInfo.GroupName = groupInfo.GroupName buildInfo.Logo = appVerInfo.Logo buildInfo.Name = appVerInfo.Name buildInfo.Version = appVerInfo.Version buildInfo.IsTemp = false buildInfo.NeedCrt = domainInfo.NeedCrt buildInfo.AppId = info.AppID accountService := NewAccountInfoService() buildInfo.DeveloperStatus = int32(accountService.getAccountStatus(groupInfo)) //buildInfoCacheByte, _ := json.Marshal(buildInfo) //avs.rc.Set(ctx, avs.getTrialInfoCacheKey(codeId), string(buildInfoCacheByte), config.Cfg.RedisTrialExpireTime) return buildInfo, rsp } func (as *AppAppletInfoService) getTempAppInfo(ctx context.Context, codeId string) (*pb.BuildAppInfo, *utility.SvrRsp) { //todo 获取临时小程序数据 //tempRspInfo, err := as.appRepo.getTempAppInfo(ctx, codeId, 1) /*rsp := utility.DefaultSvrRsp() tempRspInfo, err := as.appRepo.getTempAppInfo(ctx, codeId, 1) common.GLog.Infof("getTempAppInfo rsp:%+v,err:%+v", tempRspInfo, err) if err != nil { common.GLog.Errorf("getTempAppInfo err:%s", err.Error()) return nil, rsp.SetLoc(gin.H{}, http.StatusInternalServerError, common.FS_SERVER_ERR) } buildInfo := new(pb.BuildAppInfo) buildInfo.CodeId = codeId buildInfo.CoreDescription = tempRspInfo.CoreDescription buildInfo.Created = tempRspInfo.Created buildInfo.CreatedBy = tempRspInfo.CreatedBy buildInfo.CustomData = ConvertRpcCustomDataToPb(tempRspInfo.CustomData) buildInfo.CustomData.AppRuntimeDomain = new(pb.AppRuntimeDomain) buildInfo.GroupId = tempRspInfo.GroupID buildInfo.GroupName = tempRspInfo.GroupName buildInfo.Logo = tempRspInfo.Logo buildInfo.Name = tempRspInfo.Name buildInfo.Version = tempRspInfo.Version buildInfo.IsTemp = true buildInfo.NeedCrt = tempRspInfo.NeedCrt buildInfo.AppId = tempRspInfo.AppID return buildInfo, rsp.SetLoc(gin.H{}, http.StatusOK, common.OK)*/ return nil, nil } func (as *AppAppletInfoService) GetDevInfo(ctx context.Context, codeId, sdkKey string) (*pb.BuildAppInfo, *utility.SvrRsp) { rsp := utility.DefaultSvrRsp() buildInfo := new(pb.BuildAppInfo) /*buildInfoCacheByte, err := avs.rc.GetBytes(ctx, avs.getDevInfoCacheKey(codeId)) if err == nil { if err = json.Unmarshal(buildInfoCacheByte, buildInfo); err == nil { log.Infof("GetDevInfo from cache ...") return buildInfo, rsp.SetLoc(gin.H{}, http.StatusOK, common.OK) } }*/ info, err := as.appBuildInfoRepo.GetInfoById(ctx, codeId) if err != nil { log.Errorf("GetDevInfo get info err:%s", err.Error()) if as.appBuildInfoRepo.NotFound(err) { return nil, rsp.SetLoc(http.StatusNotFound, utility.FS_NOT_FOUND) } return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_DB_ERR) } appVerInfo, err := as.appRepo.GetAppVerInfo(ctx, info.AppID, 0) if err != nil { log.Errorf("GetDevInfo GetAppVerInfo err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_DB_ERR) } groupInfo, err := hCaller.GetGroupInfoByUserId(ctx, appVerInfo.GroupID) if err != nil { log.Errorf("GetDevInfo GetGroupInfoByUserId err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } //// 获取开发者信息 //developerInfo, err := client.GetDeveloperInfo(ctx, appVerInfo.DeveloperID) //if err != nil { // log.Errorf("GetDeveloperInfo err:%s", err.Error()) // return nil, rsp.SetLoc(gin.H{}, http.StatusInternalServerError, common.FS_SERVER_ERR) //} //status := avs.account.getAccountStatus(groupInfo, developerInfo) if config.Cfg.IsUatEnv() { if !hCaller.UatOrganStatusIsValid(groupInfo.ReviewStatus) { log.Errorf("GetDevInfo get info organ info invalid,code id:%s", codeId) return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_ORGAN_STATUS_INVALID) } } else { if !hCaller.OrganStatusIsValid(groupInfo.ReviewStatus) { log.Errorf("GetDevInfo get info organ info invalid,code id:%s", codeId) return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_ORGAN_STATUS_INVALID) } } //if !client.OrganStatusIsValid(groupInfo.ReviewStatus) { // log.Errorf("GetDevInfo get info organ info invalid,code id:%s", codeId) // return nil, rsp.SetLoc(gin.H{}, http.StatusForbidden, common.FS_ORGAN_STATUS_INVALID) //} //支付信息过期校验 if config.Cfg.OpenPurchAuth && config.Cfg.PublishEnv == config.ENV_UAT { appStatus, err := as.CheckIdStatus(ctx, appVerInfo.AppID) if err != nil { log.Errorf("CheckIdStatus err:%s,appId:%s", err.Error(), appVerInfo.AppID) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } if appStatus == httpcall.PAY_ID_STATUS_EXPIRE { log.Errorf("check appid purch status no ok ") return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_APP_PAY_EXPIRE) } } domainInfo, err := hCaller.GetAppDomainByOrganId(ctx, appVerInfo.GroupID) if err != nil { log.Errorf("InternalGetAppVerInfo ger domain info err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } log.Debugf("get group id:%s,sdkKey:%s", appVerInfo.GroupID, sdkKey) inWhiteList := utils.InArry(sdkKey, config.WhiteSDKArry) if !inWhiteList { repo := impl.InitBindingRepo() bindingInfo, err := repo.GetInfoBySdkKeyOrganId(ctx, appVerInfo.GroupID, sdkKey) if err != nil { log.Errorf("GetInfoBySdkKeyOrganId err:%s", err.Error()) if repo.NotFound(err) { return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_BIND_NOT_FOUND) } return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } if bindingInfo.CooperateStatus.Value != entity.StBindValid { log.Errorf("GetDevInfo binding bind invalid,binding info:%+v", bindingInfo) return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_COOPERATION_TERMINATED) } //支付信息校验 if config.Cfg.OpenPurchAuth && config.Cfg.PublishEnv == entity.ENV_UAT { bindStatus, err := as.CheckIdStatus(ctx, bindingInfo.BindingID) if err != nil { log.Errorf("CheckIdStatus err:%s,bindingId:%s", err.Error(), bindingInfo.BindingID) return nil, rsp.SetLoc(http.StatusInternalServerError, utility.FS_SERVER_ERR) } if bindStatus == httpcall.PAY_ID_STATUS_EXPIRE { log.Errorf("binding id pay check no ok ") return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_BIND_PAY_EXPIRE) } } appAssBind := false for _, v := range bindingInfo.AppInfos { if v.AppID == appVerInfo.AppID { appAssBind = true } } if !appAssBind { log.Errorf("GetDevInfo sdk key not ass binding,appId:[%s]", appVerInfo.AppID) return nil, rsp.SetLoc(http.StatusForbidden, utility.FS_APP_NOT_ASS_BIND) } } buildInfo.CodeId = info.Id buildInfo.CoreDescription = appVerInfo.CoreDescription buildInfo.Created = info.Created buildInfo.CreatedBy = info.CreatedBy err, errCode, customData := ConvertModelCustomDataToPb(ctx, info.GroupID, appVerInfo.CustomData, domainInfo, "cache") if err != nil { log.Errorf("ConvertModelCustomDataToPb err:%s", err.Error()) return nil, rsp.SetLoc(http.StatusInternalServerError, errCode) } buildInfo.CustomData = customData buildInfo.GroupId = info.GroupID buildInfo.GroupName = groupInfo.GroupName buildInfo.Logo = appVerInfo.Logo buildInfo.Name = appVerInfo.Name buildInfo.Version = info.Version buildInfo.AppId = info.AppID buildInfo.IsTemp = false buildInfo.NeedCrt = domainInfo.NeedCrt accountService := NewAccountInfoService() buildInfo.DeveloperStatus = int32(accountService.getAccountStatus(groupInfo)) //buildInfoCacheByte, _ = json.Marshal(buildInfo) //avs.rc.Set(ctx, avs.getDevInfoCacheKey(codeId), string(buildInfoCacheByte), config.Cfg.RedisTrialExpireTime) return buildInfo, rsp } func (as *AppAppletInfoService) GetTrialInfoByAppId(ctx context.Context, appId string) (*entity.AppBuildInfo, error) { return as.appBuildInfoRepo.GetTrialInfoByAppId(ctx, appId) } func (as *AppAppletInfoService) GetLatestInfoByAppId(ctx context.Context, appId string) (*entity.AppBuildInfo, error) { return as.appBuildInfoRepo.GetLatestInfoByAppId(ctx, appId) } func (as *AppAppletInfoService) CheckIdStatus(ctx context.Context, id string) (int, error) { return httpcall.PAY_ID_STATUS_USING, nil /*switch config.Cfg.ReqType { case "grpc": return grpc.PurchasingGetIdStatus(ctx, id) default: status, _, err := hCaller.PayCheckIdStatus(ctx, id) return status, err }*/ } type MenuInfoFetcher interface { GetMenuRspInfo(ctx context.Context) (*proto.MenuInfoRspData, error) } func ConvertModelCustomDataToPb( ctx context.Context, //rs MenuInfoFetcher, groupId string, data entity.CustomDataInfo, domainInfo *httpcall.DomainResponseData, sdkVer string, ) (error, string, *pb.CustomData) { var err error if domainInfo == nil { domainInfo, err = hCaller.GetDomainInfoByOrganId(ctx, groupId) if err != nil { log.Errorf("InternalGetAppVerInfo ger domain info err:%s", err.Error()) return err, utility.FS_GET_DOMAIN_INFO_ERROR, nil } } menuRsp, err := GetMenuRspInfo(ctx) if err != nil { log.Errorf("GetDevInfo GetMenuRspInfo err:%+v", err) return err, utility.FS_SERVER_ERR, nil } apiData, err := hCaller.GetApiList(ctx, groupId) if err != nil { log.Errorf("get api list err:%s", err.Error()) return err, utility.FS_SERVER_ERR, nil } res := new(pb.CustomData) res.ApiInfo = nil if apiData != nil { res.ApiInfo = make([]*pb.ApiInfoRspData, 0) for _, v := range apiData { res.ApiInfo = append(res.ApiInfo, &pb.ApiInfoRspData{Url: v.Url, ApiName: v.ApiName}) } } if menuRsp != nil { res.MenuInfo = new(pb.MenuInfoRspData) res.MenuInfo.Total = int32(menuRsp.Total) res.MenuInfo.List = make([]*pb.MenuInfoRspDataItem, 0) for _, v := range menuRsp.List { res.MenuInfo.List = append(res.MenuInfo.List, &pb.MenuInfoRspDataItem{Name: v.Name, Id: v.ID, Image: v.Image}) } } res.DetailDescription = data.DetailDescription res.VersionDescription = data.VersionDescription res.SourceFile = make([]*pb.SourceFileData, 0) for _, v := range data.SourceFile { item := &pb.SourceFileData{ FileMd5: v.FileMd5, Name: v.Name, UploadDate: v.UploadDate, Url: v.Url, SourceFileUrl: "", BasicPackVer: v.BasicPackVer, } if sdkVer != "" { isEncry := false if sdkVer == "cache" { isEncry = true } else { isEncry, err = GetSdkVerEncryResult(ctx, sdkVer) if err != nil { return err, utility.FS_SERVER_ERR, nil } } if isEncry && v.EncryptedUrl != "" { // && v.EncryptedFileMd5 != "" { item.Url = v.EncryptedUrl item.FileMd5 = v.EncryptedFileMd5 } } for _, val := range v.EncryptPackages { item.Packages = append(item.Packages, &pb.Package{ Root: val.Root, Name: val.Name, Pages: val.Pages, Independent: val.Independent, Filename: val.Filename, FileUrl: val.FileUrl, FileMd5: val.FileMd5, }) } res.SourceFile = append(res.SourceFile, item) } res.AppRuntimeDomain = GetPbRuntimeDomains(domainInfo) return nil, "", res } func GetSdkVerEncryResult(ctx context.Context, sdkVer string) (bool, error) { var isEncry bool var err error /*isEncry, ok := cache.GetSdkVerResult(ctx, sdkVer) if ok { return isEncry, nil }*/ switch config.Cfg.ReqType { case "grpc": isEncry, err = grpc.GetSdkVerEncrypted(ctx, sdkVer) default: isEncry, err = httpcall.NewClient().GetSdkVerIsEncrypted(ctx, sdkVer) } if err != nil { return false, err } //cache.SetSdkVerResult(ctx, sdkVer, isEncry) return isEncry, nil } func GetPbRuntimeDomains(domainInfo *httpcall.DomainResponseData) *pb.AppRuntimeDomain { result := &pb.AppRuntimeDomain{} result.Business = &pb.AppRuntimeDomain_Business{Domains: make([]string, 0)} if domainInfo.Business.Domains != nil { result.Business.Domains = domainInfo.Business.Domains } result.Service = &pb.AppRuntimeDomain_Service{ Download: make([]string, 0), Request: make([]string, 0), Socket: make([]string, 0), Upload: make([]string, 0), } if domainInfo.Service.Download != nil { result.Service.Download = domainInfo.Service.Download } if domainInfo.Service.Request != nil { result.Service.Request = domainInfo.Service.Request } if domainInfo.Service.Socket != nil { result.Service.Socket = domainInfo.Service.Socket } if domainInfo.Service.Download != nil { result.Service.Upload = domainInfo.Service.Upload } result.Whitelist = &pb.AppRuntimeDomain_Whitelist{Domains: make([]string, 0)} if domainInfo.Whitelist.Domains != nil { result.Whitelist.Domains = domainInfo.Whitelist.Domains } result.Blacklist = &pb.AppRuntimeDomain_Blacklist{Domains: make([]string, 0)} if domainInfo.Blacklist.Domains != nil { result.Blacklist.Domains = domainInfo.Blacklist.Domains } return result } func GetMenuRspInfo(ctx context.Context) (*proto.MenuInfoRspData, error) { //非私有化环境置为nil if !config.Cfg.IsPrivateEnv() { return nil, nil } menuCreated, err := MenuHasCreated(ctx) if err != nil { return nil, err } if !menuCreated { return nil, nil } result := new(proto.MenuInfoRspData) result.List = make([]proto.MenuInfoRspDataItem, 0) /*cacheRsp, err := rs.menuCache.Get(ctx) if err == nil { result.Total = cacheRsp.Total for _, m := range cacheRsp.List { item := proto.MenuInfoRspDataItem{} item.ID = m.ID item.Name = m.Name item.Image = m.Image result.List = append(result.List, item) } return result, nil }*/ menuCacheInfo := apiproto.GetAllMenuRsp{} repoRspList, total, err := impl.InitMenuInfoRepo().GetAllMenuList(ctx, []string{"sortNum"}) if err != nil { return nil, err } result.Total = total menuCacheInfo.Total = total for _, m := range repoRspList { item := proto.MenuInfoRspDataItem{} item.ID = m.InfoId item.Name = m.Name item.Image = m.ImageUrl result.List = append(result.List, item) cacheItem := apiproto.GetAllMenuRspItem{ TraceId: m.TraceId, Name: m.Name, ID: m.InfoId, Image: m.ImageUrl, SortNum: m.SortNum, CreateTime: m.CreateTime, UpdateTime: m.UpdateTime, UpdateOperator: m.UpdateOperator, } menuCacheInfo.List = append(menuCacheInfo.List, cacheItem) } return result, nil } type EncryptInfo struct { ApiServer string `json:"apiServer"` CodeId string `json:"codeId"` Type string `json:"type"` Uuid string `json:"uuid"` } func (as *AppAppletInfoService) getQrCodeSign(t, codeId, apiServer string) string { s, _ := json.Marshal(EncryptInfo{ApiServer: apiServer, Type: t, CodeId: codeId, Uuid: uuid.NewV4().String()}) return utils.EncodeAESContent(string(s)) } func MenuHasCreated(ctx context.Context) (bool, error) { //先从redis中取 val, err := redis.RedisGet(ctx, utility.MenuCreatedKey) fmt.Println("get string val:", val, ",err:", err) if err == nil { return true, nil } if !redis.RedisNotFound(err) { return false, err } menuCount, err := impl.InitMenuInfoRepo().AllCount(ctx) if err != nil { return false, err } if menuCount > 0 { redis.RedisSet(ctx, utility.MenuCreatedKey, utility.MenuCreatedValue, 0) return true, nil } return false, nil } func ConvertWechatLoginInfoToPb(info *proto.WechatLoginInfo) *pb.WechatLoginInfo { rsp := new(pb.WechatLoginInfo) rsp.WechatOriginId = info.WechatOriginId rsp.ProfileUrl = info.ProfileUrl rsp.PhoneUrl = info.PhoneUrl rsp.PaymentUrl = info.PaymentUrl for _, v := range info.ExtUrls { ext := pb.ExtUrls{ FieldName: v.FieldName, PageUrl: v.PageUrl, } rsp.ExtUrls = append(rsp.ExtUrls, &ext) } return rsp }