package application import ( "errors" "finclip-app-manager/domain/entity" "finclip-app-manager/domain/entity/proto/apiproto" "finclip-app-manager/domain/service" "finclip-app-manager/infrastructure/client/httpcall" "finclip-app-manager/infrastructure/config" "finclip-app-manager/infrastructure/kafka" "finclip-app-manager/infrastructure/utility" "net/http" "strings" "time" "github.com/gin-gonic/gin" "gitlab.finogeeks.club/finclip-backend/apm" ) /** * @api {GET} * @apiGroup Finclip App Manager * @apiParam (RequestBody) {string} name * @apiParam (RequestBody) {string} owner * @apiParamExample {json} Request-Example: * { * "name": "sdfasd", * "owner": "wqef" * } * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "data": { * "bindingId": "61f4f3ce5d3ef200013d9240", * "name": "sdfasd", * "bundleInfos": null, * "createdInfo": { * "createdBy": "61de2c5fe1ba8c000175c2b2", * "createdAt": 1643443150345 * }, * "groupId": "61de2c5fe1ba8c000175c2b3", * "groupName": "王麻子豆腐", * "cooperateStatus": { * "value": "Valid", * "reason": "", * "lastUpdated": 1643443150345, * "modifiedBy": "18220595937" * }, * "cooperateValidStatus": { * "reason": "", * "lastUpdated": 0, * "modifiedBy": "" * }, * "cooperateInvalidStatus": { * "reason": "", * "lastUpdated": 0, * "modifiedBy": "" * }, * "appInfos": null, * "owner": "wqef", * "expire": 0, * "apiServer": "https://finchat-mop-b.finogeeks.club" * }, * "errcode": "OK", * "error": "" * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func DevCreateBinding(c *gin.Context) { CreateBinding(c, false) } func AdminCreateBinding(c *gin.Context) { CreateBinding(c, true) } func CreateBinding(c *gin.Context, isAdmin bool) { traceCtx := apm.ApmClient().TraceContextFromGin(c) rsp := make(map[string]interface{}) bind := entity.Binding{} if err := c.ShouldBindJSON(&bind); err != nil { log.Errorf("CreateBinding bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, rsp) return } log.Infof("CreateBinding req:%+v", bind) if len(bind.BundleInfos) > config.GetConfig().AddAvailableBundleNum { log.Errorf("CreateBinding binding bundle id num err:%s", "over limit 2") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, rsp) return } svr := service.NewBindingService() httpCode, errCode, rspData := svr.Create(traceCtx, c, &bind, isAdmin) utility.MakeLocRsp(c, httpCode, errCode, rspData) return } func GetBindingUsedInfo(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) svr := service.NewBindingService() httpCode, errCode, rspData := svr.GetBindingUsed(traceCtx) utility.MakeLocRsp(c, httpCode, errCode, rspData) return } type GetLicenseTerminalRsp struct { IsWindows bool `json:"isWindows"` IsMac bool `json:"isMac"` IsLinux bool `json:"isLinux"` IsIOS bool `json:"isIOS"` IsAndroid bool `json:"isAndroid"` } func GetLicenseTerminal(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) rsp := make(map[string]interface{}) licenseInfo, err := hCaller.GetLicense(traceCtx) if err != nil { log.Errorf("CreateBinding bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_SERVER_ERR, rsp) } rspData := GetLicenseTerminalRsp{} rspData.IsAndroid = licenseInfo.IsAndroid rspData.IsWindows = licenseInfo.IsWindows rspData.IsMac = licenseInfo.IsMac rspData.IsLinux = licenseInfo.IsLinux rspData.IsIOS = licenseInfo.IsIOS utility.MakeLocRsp(c, http.StatusOK, utility.OK, rspData) return } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func DevListBindings(c *gin.Context) { listBindings(c, true) } type ListBindingsReq struct { SearchText string `form:"searchText"` SearchFields string `form:"searchFields"` PageSize int `form:"pageSize"` PageNo int `form:"pageNo"` } func listBindings(c *gin.Context, filterGroup bool) { traceCtx := apm.ApmClient().TraceContextFromGin(c) req := ListBindingsReq{} if err := c.BindQuery(&req); err != nil { log.Errorf("ListBindingsReq bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, gin.H{}) return } log.Infof("ListBindingsReq req:%+v", req) if filterGroup { developerID := c.Request.Header.Get("x-consumer-custom-id") groupInfo, err := hCaller.GetGroupInfoByUserId(traceCtx, developerID) if err != nil { utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_GET_ACCOUNTINFO_ERROR, nil) return } svr := service.NewBindingService() binds, total, err := svr.ListBindings(traceCtx, groupInfo.GroupID, req.SearchText, req.PageNo, req.PageSize) if err != nil { utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, nil) return } c.JSON(http.StatusOK, gin.H{ "total": total, "list": binds, }) return } svr := service.NewBindingService() binds, total, err := svr.ListBindings(traceCtx, "", req.SearchText, req.PageNo, req.PageSize) if err != nil { utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, nil) return } c.JSON(http.StatusOK, gin.H{ "total": total, "list": binds, }) } type DevListBindingsV2Req struct { PullType string `form:"pullType"` BindStatus string `form:"bindStatus"` PageNo int `form:"pageNo"` PageSize int `form:"pageSize"` SearchTxt string `form:"searchTxt"` SortType string `form:"sortType"` Platform int `form:"platform,default=2"` } /** * @api {GET} * @apiGroup Finclip App Manager * @apiParam (RequestBody) {string} bindStatus * @apiParam (RequestBody) {string} searchTxt * @apiParam (RequestBody) {string} pageSize * @apiParam (RequestBody) {string} pageNo * @apiParam (RequestBody) {string} sortType * @apiParam (RequestBody) {string} pullType * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "data": { * "total": 1429, * "list": [ * { * "bindingId": "61f4f3ce5d3ef200013d9240", * "name": "sdfasd", * "groupName": "王麻子豆腐", * "appInfos": null, * "bundleInfos": [], * "createdInfo": { * "createdBy": "61de2c5fe1ba8c000175c2b2", * "createdAt": 1643443150345 * }, * "groupId": "61de2c5fe1ba8c000175c2b3", * "cooperateStatus": { * "value": "Valid", * "reason": "", * "lastUpdated": 1643443150345, * "modifiedBy": "18220595937" * }, * "cooperateValidStatus": { * "reason": "", * "lastUpdated": 0, * "modifiedBy": "" * }, * "cooperateInvalidStatus": { * "reason": "", * "lastUpdated": 0, * "modifiedBy": "" * }, * "owner": "wqef", * "expire": 9999999999999, * "apiServer": "https://finchat-mop-b.finogeeks.club", * "apmServer": "https://finchat-mop-b.finogeeks.club" * } * ] * }, * "errcode": "OK", * "error": "" * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func DevListBindingsV2(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) req := DevListBindingsV2Req{} if err := c.Bind(&req); err != nil { log.Errorf("DevListBindingsV2 bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, make(map[string]interface{})) return } userId := c.GetHeader(entity.ACCOUNT_ID_HEADER_KEY) if userId == "" { log.Errorf("DevListBindingsV2 bind err:%s", "user id empty") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, make(map[string]interface{})) return } if req.PageSize == 0 { req.PageSize = 10 } svrReq := apiproto.DevListBindingReq{ PullType: req.PullType, BindStatus: req.BindStatus, SortType: req.SortType, PageNo: req.PageNo, PageSize: req.PageSize, SearchTxt: req.SearchTxt, UserId: userId, Platform: req.Platform, } log.Infof("DevListBindingsV2 req:%+v", svrReq) svr := service.NewBindingService() svr.DevListBinding(c, traceCtx, &svrReq) return } func SyncOrganBinding(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) req := apiproto.SyncOrganBindingReq{} if err := c.ShouldBindJSON(&req); err != nil { log.Errorf("SyncOrganBinding ShouldBindJSON err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, make(map[string]interface{})) return } svr := service.NewBindingService() httpCode, errCode, rsp := svr.SyncOrganBinding(traceCtx, req) utility.MakeLocRsp(c, httpCode, errCode, rsp) } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "data": { * "bindingId": "609b93a80f0ca30001292df2", * "name": "autockwms", * "bundleInfos": [ * { * "bundleId": "autofpgwj", * "remark": "ios_android", * "SDKKey": "lvqyfRXHkVyNY0GnY6a6SQ==", * "SDKID": "775f549788c238b5", * "isFirstCreate": true, * "createdAt": 1620808617522, * "createdAccount": "15473501296", * "createdBy": "autotest" * } * ], * "createdInfo": { * "createdBy": "", * "createdAt": 0 * }, * "groupId": "609b92452a68150001e7875d", * "groupName": "autotxdzr", * "cooperateStatus": { * "value": "Valid", * "reason": "", * "lastUpdated": 1620808616325, * "modifiedBy": "15473501296" * }, * "cooperateValidStatus": { * "reason": "", * "lastUpdated": 0, * "modifiedBy": "" * }, * "cooperateInvalidStatus": { * "reason": "", * "lastUpdated": 0, * "modifiedBy": "" * }, * "appInfos": [], * "owner": "test", * "expire": 0, * "apiServer": "https://finchat-mop-b.finogeeks.club" * }, * "errcode": "OK", * "error": "" * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func GetBindingDetail(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) bindingId := c.Param("bindingId") if bindingId == "" { log.Errorf("GetBindingDetail bind id empty") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, make(map[string]interface{})) return } svr := service.NewBindingService() svr.Detail(c, traceCtx, bindingId) return } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ type DevListAllAppidInfoReq struct { AppIdList string `form:"appIdList"` } func DevListAllAppidInfo(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) req := DevListAllAppidInfoReq{} if err := c.BindQuery(&req); err != nil { log.Errorf("DevListAllAppidInfo bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_PARAM_ERR, gin.H{}) return } log.Infof("DevListAllAppidInfo req:%+v", req) if req.AppIdList == "" { utility.MakeLocRsp(c, http.StatusOK, utility.OK, gin.H{}) return } appIdList := strings.Split(req.AppIdList, ",") if len(appIdList) > 100 { log.Errorf("DevListAllAppidInfo appid over limit!") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_PARAM_ERR, gin.H{}) return } svr := service.NewAppService() apps, err := svr.GetAppsByAppIds(traceCtx, appIdList) if err != nil { log.Errorf("DevListAllAppidInfo GetAppsByAppIds err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, gin.H{}) return } pubApps := []string{} for _, v := range apps { _, err := svr.GetOnlineAppVer(traceCtx, v.AppID) if err == nil { pubApps = append(pubApps, v.AppID) } } c.JSON(http.StatusOK, gin.H{"total": len(apps), "list": apps, "pubApps": pubApps}) } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func UpdateBinding(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) req := apiproto.BindingUpdateRequest{} errRsp := make(map[string]interface{}) if err := c.ShouldBindJSON(&req); err != nil { log.Errorf("UpdateBinding binding err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, errRsp) return } if req.BindingID == "" { log.Errorf("UpdateBinding binding id empty !!!") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_LACK_OF_BINDING_ID, errRsp) return } log.Infof("UpdateBinding req:%+v", req) developerID := c.Request.Header.Get("X-Consumer-Custom-ID") groupInfo, err := hCaller.GetGroupInfoByUserId(traceCtx, developerID) if err != nil { log.Errorf("UpdateBinding get group id err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_GET_GROUP_FAILED, errRsp) return } svr := service.NewBindingService() bind, err := svr.GetInfo(traceCtx, req.BindingID) if err != nil && !svr.NotFound(err) { log.Errorf("UpdateBinding get binding info err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, errRsp) return } log.Infof("UpdateBinding bind info:%+v,err:%+v", bind, err) if svr.NotFound(err) { log.Errorf("UpdateBinding get binding info err:%s", "NOT FOUND ID") utility.MakeLocRsp(c, http.StatusNotFound, utility.FS_NOT_FOUND, errRsp) return } if groupInfo.GroupID != bind.GroupID { log.Errorf("UpdateBinding group id mismatch err:%s", bind.GroupID) utility.MakeLocRsp(c, http.StatusForbidden, utility.FS_FORBIDDEN, errRsp) return } accountInfo, err := httpcall.NewClient().GetAccountInfo(traceCtx, developerID) if err != nil { log.Errorf("UpdateBinding get account info err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_GET_ACCOUNTINFO_ERROR, errRsp) return } if bind.PlatForm == entity.BINGING_PLATFORM_OPER && (req.Operation != entity.OpBindingAssociate && req.Operation != entity.OpBindingDisassociate) { log.Errorf("bind platform:%d Operation:%s not allowed", bind.PlatForm, req.Operation) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_MANAGE_APP_NO_AUTH, errRsp) return } switch req.Operation { case entity.OpBindingAssociate: if len(req.AppIDs) <= 0 { utility.MakeLocRsp(c, http.StatusOK, utility.OK, errRsp) return } // 直接关联 if config.Cfg.PublishEnv == entity.ENV_FDEP { err = applyAssociate(c, req.AppIDs, bind, groupInfo.GroupID, accountInfo.Account) } else { associate(c, req.AppIDs, bind, groupInfo.GroupID, accountInfo.Account) return } case entity.OpBindingDisassociate: if len(req.AppIDs) <= 0 { utility.MakeLocRsp(c, http.StatusOK, utility.OK, errRsp) return } err = disassociate(c, req.AppIDs, bind, developerID, accountInfo.Account) case entity.OpBindingRecooperate: err = recooperate(c, &req, bind, developerID, accountInfo.Account) case entity.OpBindingDiscooperate: err = discooperate(c, &req, bind, developerID, accountInfo.Account) case entity.OpBindingModifyName: err = modifyBindingName(c, &req, bind, developerID, accountInfo.Account, false) case entity.OpBindBundle: statusCode, rsp := svr.BindBundles(traceCtx, req.BindingID, groupInfo.GroupID, accountInfo, req.BundlesInfo, nil, false) if statusCode != utility.OK && statusCode != utility.FS_BUNDLE_ID_COUNT_OVER_TO_WEB_ERR { utility.MakeLocRsp(c, http.StatusBadRequest, statusCode, errRsp) } else { utility.MakeLocRsp(c, http.StatusOK, statusCode, rsp) } return case entity.OpUpdateBundle: svr := service.NewBindingService() statusCode, rsp := svr.UpdateBundles(traceCtx, req.BindingID, groupInfo.GroupID, req.BundlesInfo) if statusCode != utility.OK && statusCode != utility.FS_BUNDLE_ID_COUNT_OVER_TO_WEB_ERR { utility.MakeLocRsp(c, http.StatusBadRequest, statusCode, errRsp) } else { utility.MakeLocRsp(c, http.StatusOK, statusCode, rsp) } return case entity.OpMoveBundle: if req.ToBindingID == "" { log.Errorf("UpdateBinding to binding id empty !!!") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FC_LACK_OF_TO_BINDING_ID, errRsp) return } if req.BindingID == req.ToBindingID { log.Errorf("UpdateBinding binding id:%s equal to binding id:%s", req.BindingID, req.ToBindingID) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FC_BINDING_ID_EQUAL_TO_INDING_ID, errRsp) return } httpCode, errCode, rsp := svr.MoveBundles(traceCtx, bind, &req, entity.BINGING_PLATFORM_ORGAN) utility.MakeLocRsp(c, httpCode, errCode, rsp) return default: log.Errorf("UpdateBinding operation err,op:%v", req.Operation) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_INVALID_BINDING_OPERATION, errRsp) return } if err == nil { utility.MakeLocRsp(c, http.StatusOK, utility.OK, errRsp) return } } func modifyBindingName(c *gin.Context, req *apiproto.BindingUpdateRequest, bind *entity.Binding, developerID string, account string, isAdmin bool) error { traceCtx := apm.ApmClient().TraceContextFromGin(c) errRsp := make(map[string]interface{}) if bind.CooperateStatus.Value != entity.StBindValid { log.Errorf("modifyBindingName bind CooperateStatus invalid,bind id:%s", bind.BindingID) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_INVALID_COOPERATE_STATUS, errRsp) return errors.New(entity.ErrFake) } //上报用 groupInfo, err := hCaller.GetGroupInfoByUserId(traceCtx, developerID) if err != nil || groupInfo == nil || groupInfo.GroupID == "" { log.Errorf("modifyBindingName get group info err:%+v", err) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_GET_GROUP_FAILED, errRsp) return errors.New(entity.ErrFake) } svr := service.NewBindingService() result, err := svr.GetBindingByGroupIdAndName(traceCtx, groupInfo.GroupID, req.AppName, isAdmin) if err != nil && !svr.NotFound(err) { log.Errorf("modifyBindingName get info err:%+v", err) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, errRsp) return errors.New(entity.ErrFake) } if !svr.NotFound(err) && result.BindingID != req.BindingID { log.Errorf("modifyBindingName found binding !!!") utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_BINDING_NAME_REPEAT, errRsp) return errors.New(entity.ErrFake) } logExp := make(map[string]interface{}) go hCaller.AddOperateLog(c, groupInfo.GroupID, kafka.GenContent(kafka.BIND_UP_LOG, bind.Name, req.AppName), logExp, account) bind.Name = req.AppName bind.Owner = req.Owner //这里需要校验应用名不能重复 err = svr.UpdateByBindId(traceCtx, req.BindingID, bind) if err != nil { log.Errorf("modifyBindingName up binding err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, errRsp) return errors.New(entity.ErrFake) } return nil } func discooperate(c *gin.Context, req *apiproto.BindingUpdateRequest, bind *entity.Binding, developerID string, account string) error { traceCtx := apm.ApmClient().TraceContextFromGin(c) errRsp := make(map[string]interface{}) if bind.CooperateStatus.Value != entity.StBindValid { log.Errorf("discooperate bind CooperateStatus invalid,bind id:%s", bind.BindingID) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_INVALID_COOPERATE_STATUS, errRsp) return errors.New(entity.ErrFake) } timestamp := time.Now().UnixNano() / 1000000 bind.CooperateStatus = entity.Status{ Value: entity.StBindInvalid, LastUpdated: timestamp, ModifiedBy: account, } bind.CooperateInvalidStatus = entity.SpecificStatus{ LastUpdated: timestamp, ModifiedBy: account, } //调用支付系统进行权限校验 if config.GetConfig().OpenPurchAuth && config.GetConfig().PublishEnv == entity.ENV_UAT { applyReq := httpcall.PayAddLimitReq{} applyReq.Type = httpcall.PAY_ADD_TYPE_BINDING applyReq.AccountId = developerID applyReq.BusinessId = bind.BindingID applyReq.BusinessName = bind.Name _, httpCode, err := hCaller.PayUpdateLimit(traceCtx, &applyReq) if err != nil { utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_SYSTEM_CALL, errRsp) return errors.New(entity.ErrFake) } if httpCode != http.StatusOK { utility.MakeLocRsp(c, httpCode, utility.FC_OPERA_LIMIT_BIND_OVER_ERROR, errRsp) return errors.New(entity.ErrFake) } } else { n := httpcall.AddLimitInfoReq{ Type: "binding", OrganId: bind.GroupID, AddNum: -1, } _, _, err := hCaller.AddLimitInfo(traceCtx, &n) if err != nil { log.Errorf("Failed to notify: %v\n", err) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FC_OPERA_LIMIT_BIND_OVER_ERROR, errRsp) return errors.New(entity.ErrFake) } } svr := service.NewBindingService() err := svr.UpdateByBindId(traceCtx, req.BindingID, bind) if err != nil { log.Errorf("discooperate update err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, errRsp) return errors.New(entity.ErrFake) } logExp := make(map[string]interface{}) go hCaller.AddOperateLog(c, bind.GroupID, kafka.GenContent(kafka.BIND_STOP_COOP_LOG, bind.Name), logExp, account) //更新小程序详情缓存 //rs := service.NewRuntimeService() //rs.Discooperate(traceCtx, req.BindingID) ////更新小程序版本详情缓存 //appVerSvr := service.NewAppVerService() //appVerSvr.BindCancelCoop(traceCtx, req.BindingID) //model.NewAsyncMessageRepo().GenAppStatusChangeInfo(traceCtx, model.AppStatusChangeInfo{Event: model.BindingCancelCoopreate, Info: map[string]interface{}{"bindingId": bind.BindingID}}) return nil } func recooperate(c *gin.Context, req *apiproto.BindingUpdateRequest, bind *entity.Binding, developerID string, account string) error { traceCtx := apm.ApmClient().TraceContextFromGin(c) errRsp := make(map[string]interface{}) if bind.CooperateStatus.Value != entity.StBindInvalid { log.Errorf("bind cooperate status Invalid,bind id:%s", bind.BindingID) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_INVALID_COOPERATE_STATUS, errRsp) return errors.New(entity.ErrFake) } timestamp := time.Now().UnixNano() / 1000000 bind.CooperateStatus = entity.Status{ Value: entity.StBindValid, LastUpdated: timestamp, ModifiedBy: account, } bind.CooperateValidStatus = entity.SpecificStatus{ LastUpdated: timestamp, ModifiedBy: account, } licenseInfo, err := hCaller.GetLicense(traceCtx) if err != nil { log.Errorf("GetBundleIdLimitHand get err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_LICENSE_SERVER_ERROR, errRsp) return errors.New("get license err") } svr := service.NewBindingService() httpCode, errCode, err := svr.BindingLicenseCheck(traceCtx, licenseInfo, nil, false) if err != nil { utility.MakeLocRsp(c, httpCode, errCode, errRsp) return err } //调用支付系统进行权限校验 if config.GetConfig().OpenPurchAuth && config.GetConfig().PublishEnv == entity.ENV_UAT { applyReq := httpcall.PayAddLimitReq{} applyReq.Type = httpcall.PAY_ADD_TYPE_BINDING applyReq.AccountId = developerID applyReq.BusinessId = bind.BindingID applyReq.BusinessName = bind.Name payAddRsp, httpCode, err := hCaller.PayAddLimit(traceCtx, &applyReq) if err != nil { utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_SYSTEM_CALL, errRsp) return errors.New(entity.ErrFake) } if httpCode != http.StatusOK { utility.MakeLocRsp(c, httpCode, utility.FC_OPERA_LIMIT_BIND_OVER_ERROR, errRsp) return errors.New(entity.ErrFake) } if payAddRsp.Data.EndTime == 0 { payAddRsp.Data.EndTime = MAX_EXPIRE_DATA } bind.Expire = payAddRsp.Data.EndTime } else { n := httpcall.AddLimitInfoReq{ Type: "binding", OrganId: bind.GroupID, AddNum: 1, } _, _, err := hCaller.AddLimitInfo(traceCtx, &n) if err != nil { log.Errorf("Failed to notify: %v\n", err) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FC_OPERA_LIMIT_BIND_OVER_ERROR, errRsp) return errors.New(entity.ErrFake) } } err = svr.UpdateByBindId(traceCtx, req.BindingID, bind) if err != nil { log.Errorf("bind update err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, errRsp) return errors.New(entity.ErrFake) } logExp := make(map[string]interface{}) go hCaller.AddOperateLog(c, bind.GroupID, kafka.GenContent(kafka.BIND_RECOVE_COOP_LOG, bind.Name), logExp, account) //rs := service.NewRuntimeService() //rs.Recooperate(traceCtx, req.BindingID) //model.NewAsyncMessageRepo().GenAppStatusChangeInfo(traceCtx, model.AppStatusChangeInfo{Event: model.BindingRecooprate, Info: map[string]interface{}{"bindingId": bind.BindingID}}) return nil } func disassociate(c *gin.Context, appIds []string, bind *entity.Binding, developerID string, account string) error { traceCtx := apm.ApmClient().TraceContextFromGin(c) errRsp := make(map[string]interface{}) if bind.CooperateStatus.Value != entity.StBindValid { log.Errorf("disassociate bind CooperateStatus invalid,bind id:%s", bind.BindingID) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_INVALID_COOPERATE_STATUS, errRsp) return errors.New(entity.ErrFake) } removeApps := []string{} //产品要求,加一个校验,已经取消关联的,不可重复取消 for _, id := range appIds { found := false for _, info := range bind.AppInfos { if id == info.AppID { found = true } } if !found { log.Errorf("disassociate repeat,binding id:%s", bind.BindingID) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_APP_NOT_ASSOCIATED, errRsp) return errors.New(entity.ErrFake) } removeApps = append(removeApps, id) } //更新 /*newInfos := make([]entity.AppInfo, 0) for _, info := range bind.AppInfos { found := false for _, appID := range appIds { if appID == info.AppID { found = true break } } if !found { newInfos = append(newInfos, info) } } bind.AppInfos = newInfos*/ svr := service.NewBindingService() err := svr.RemoveApps(traceCtx, bind.BindingID, removeApps) if err != nil { log.Errorf("disassociate update err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, errRsp) return errors.New(entity.ErrFake) } //小程序搜索更新绑定的sdkKeys go svr.AdminNotifySdkKey(traceCtx, removeApps, bind, httpcall.UNBIND_SDK) //这里做个上报 appSvr := service.NewAppService() logAppMap := make(map[string]string) for _, appId := range appIds { app, err := appSvr.GetAppInfoByAppId(traceCtx, appId) if err != nil { log.Errorf("GetAppInfoByAppId err:%s", err.Error()) continue } logAppMap[appId] = app.Name } logExp := make(map[string]interface{}) go hCaller.AddOperateLog(c, bind.GroupID, kafka.GenContentAssApp(kafka.BIND_CANCEL_ASS_APP_LOG, bind.Name, logAppMap), logExp, account) ////更新运行时获取小程序缓存 //rs := service.NewRuntimeService() //rs.Disassociate(traceCtx, bind.BindingID, appIds) ////更新小程序版本详情缓存 //appVerSvr := service.NewAppVerService() //appVerSvr.BindDisAssApp(traceCtx, bind.BindingID, appIds) //model.NewAsyncMessageRepo().GenAppStatusChangeInfo(traceCtx, model.AppStatusChangeInfo{Event: model.BindingDisassApps, Info: map[string]interface{}{"bindingId": bind.BindingID, "appIds": appIds}}) return nil } func associate(c *gin.Context, appIds []string, bind *entity.Binding, groupId string, account string) { traceCtx := apm.ApmClient().TraceContextFromGin(c) errRsp := make(map[string]interface{}) if bind.CooperateStatus.Value != entity.StBindValid { log.Errorf("associate bind CooperateStatus invalid,bind id:%s", bind.BindingID) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_INVALID_COOPERATE_STATUS, errRsp) return } svr := service.NewBindingService() rsp := svr.AssApps(traceCtx, c, bind.BindingID, appIds, account) //小程序搜索更新绑定的sdkkeys go svr.AdminNotifySdkKey(traceCtx, appIds, bind, httpcall.BIND_SDK) rsp.MakeRsp(c, gin.H{}) return } const ( StLinkAuditApplying = "Applying" StLinkAuditRejected = "Rejected" StLinkAuditApplied = "Applied" ) func applyAssociate(c *gin.Context, appIds []string, bind *entity.Binding, groupId string, account string) error { traceCtx := apm.ApmClient().TraceContextFromGin(c) errRsp := make(map[string]interface{}) if bind.CooperateStatus.Value != entity.StBindValid { log.Errorf("associate bind CooperateStatus invalid,bind id:%s", bind.BindingID) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_INVALID_COOPERATE_STATUS, errRsp) return errors.New(entity.ErrFake) } logAppMap := make(map[string]string) for _, appID := range appIds { appDevInfo, err := service.NewAppService().GetAppVerInfo(traceCtx, appID, 0) if err != nil && !service.NotFound(err) { log.Errorf("associate GetOne app info err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_INVALID_COOPERATE_STATUS, errRsp) return errors.New(entity.ErrFake) } ////一条一条校验 //vaild, appName, err := AllowAppAssociated(traceCtx, groupId, appID) //if err != nil { // log.Errorf("applyAssociate AllowAppAssociated err:%s", err.Error()) // MakeRsp(c, http.StatusInternalServerError, FS_DB_ERR, errRsp) // return errors.New(ErrFake) //} //if !vaild { // log.Errorf("applyAssociate AllowAppAssociated invalid !!") // MakeRsp(c, http.StatusBadRequest, FS_APP_NOT_PUBLISHED, errRsp) // return errors.New(ErrFake) //} //判断该应用是否已经关联了该小程序 found := false for _, info := range bind.AppInfos { if appID == info.AppID { found = true break } } if found { log.Errorf("applyAssociate app has exist !!") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_APP_ASSOCIATED, errRsp) return errors.New(entity.ErrFake) } svr := service.NewLinkAuditService() count, err := svr.Count(traceCtx, appID, groupId, bind.BindingID, StLinkAuditApplying) // 检查关联状态, 如果有审核中的, 报错 if err != nil && !svr.NotFound(err) { log.Errorf("applyAssociate AllowAppAssociated err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, errRsp) return errors.New(entity.ErrFake) } else if count != 0 { log.Errorf("exist an applying audit !!") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_LINK_AUDIT_APPLY_EXIST, errRsp) return errors.New(entity.ErrFake) } logAppMap[appID] = appDevInfo.Name } //日志 logExp := make(map[string]interface{}) logReq := httpcall.GenOperateDataV2Req{ OrganId: bind.GroupID, Content: kafka.GenContentAssApp(kafka.BIND_AUDIT_APPLY_LOG, bind.Name, logAppMap), Extra: logExp, Oper: "", AccountId: c.GetHeader(entity.ACCOUNT_ID_HEADER_KEY), IsDev: true, } hCaller.AddOperateLogV2(c, logReq) //临时注释 //rs := service.NewRuntimeService() //rs.ApplyAssociate(traceCtx, bind.BindingID, c.GetHeader(entity.ACCOUNT_ID_HEADER_KEY), appIds, logAppMap) return nil } type AdminUpdateBindingReq struct { Operation string `json:"operation"` BindingId string `json:"bindingId"` AppIds []string `json:"appIds"` Reason string `json:"reason"` } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func AdminUpdateBinding(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) errRsp := make(map[string]interface{}) req := apiproto.BindingUpdateRequest{} if err := c.BindJSON(&req); err != nil { log.Errorf("AdminUpdateBinding bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, errRsp) return } if req.Operation != entity.OpBindingAssociate && req.Operation != entity.OpBindingDisassociate && req.Operation != entity.OpBindingRecooperate && req.Operation != entity.OpBindingDiscooperate && req.Operation != entity.OpBindingModifyName && req.Operation != entity.OpBindBundle && req.Operation != entity.OpUpdateBundle && req.Operation != entity.OpBindingAutoBind && req.Operation != entity.OpBindingHiddenBundle && req.Operation != entity.OpMoveBundle { log.Errorf("AdminUpdateBinding type err, type:%s", req.Operation) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, errRsp) return } svr := service.NewBindingService() httpCode, errCode, rsp := svr.AdminBindingUpdate(traceCtx, c, &req) utility.MakeLocRsp(c, httpCode, errCode, rsp) } func AdminReviewBundleList(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) req := apiproto.ListReviewBundleReq{} if err := c.BindQuery(&req); err != nil { log.Errorf("AdminReviewBundleList bind query err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, gin.H{}) return } log.Infof("AdminReviewBundleList req:%+v", req) svr := service.NewBindingService() httpCode, errCode, rsp := svr.AdminReviewBundleList(traceCtx, c, &req) utility.MakeLocRsp(c, httpCode, errCode, rsp) } func UpdateReviewBundle(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) errRsp := make(map[string]interface{}) req := apiproto.UpdateReviewBundleReq{} if err := c.BindJSON(&req); err != nil { log.Errorf("UpdateReviewBundle bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, errRsp) return } svr := service.NewBindingService() httpCode, errCode, rsp := svr.UpdateReviewBundle(traceCtx, c, &req) utility.MakeLocRsp(c, httpCode, errCode, rsp) } func CheckReviewBySdkKey(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) sdkKey := c.Param("sdkkey") svr := service.NewBindingService() checkStatus := svr.CheckReviewBySdkKey(traceCtx, sdkKey) utility.MakeLocRsp(c, http.StatusOK, utility.OK, gin.H{"isReview": checkStatus}) } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func AdminListBindings(c *gin.Context) { listBindings(c, false) } /** * @api {GET} * @apiGroup Finclip App Manager * @apiParam (RequestBody) {string} bindStatus * @apiParam (RequestBody) {string} searchTxt * @apiParam (RequestBody) {string} pageSize * @apiParam (RequestBody) {string} pageNo * @apiParam (RequestBody) {string} sortType * @apiParam (RequestBody) {string} pullType * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "data": { * "total": 1429, * "list": [ * { * "bindingId": "61f4f3ce5d3ef200013d9240", * "name": "sdfasd", * "groupName": "王麻子豆腐", * "appInfos": null, * "bundleInfos": [], * "createdInfo": { * "createdBy": "61de2c5fe1ba8c000175c2b2", * "createdAt": 1643443150345 * }, * "groupId": "61de2c5fe1ba8c000175c2b3", * "cooperateStatus": { * "value": "Valid", * "reason": "", * "lastUpdated": 1643443150345, * "modifiedBy": "18220595937" * }, * "cooperateValidStatus": { * "reason": "", * "lastUpdated": 0, * "modifiedBy": "" * }, * "cooperateInvalidStatus": { * "reason": "", * "lastUpdated": 0, * "modifiedBy": "" * }, * "owner": "wqef", * "expire": 9999999999999, * "apiServer": "https://finchat-mop-b.finogeeks.club", * "apmServer": "https://finchat-mop-b.finogeeks.club" * } * ] * }, * "errcode": "OK", * "error": "" * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func NewAdminListBindings(c *gin.Context) { var ( traceCtx = apm.ApmClient().TraceContextFromGin(c) req = apiproto.ListBindingsReq{} errRsp = make(map[string]interface{}) ) if err := c.BindQuery(&req); err != nil { log.Errorf("list bindings bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, errRsp) return } log.Infof("get bindings seq req:%+v", req) if req.PageSize == 0 { req.PageSize = 100 } svr := service.NewBindingService() svr.ListBinding(c, traceCtx, req) return } /** * @api {GET} * @apiGroup Finclip App Manager * @apiParam (RequestBody) {string} appId * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "data": { * "total": 1429, * "list": [ * { * "bindingId": "61f4f3ce5d3ef200013d9240", * "name": "sdfasd", * "groupName": "王麻子豆腐", * "appInfos": null, * "bundleInfos": [], * "createdInfo": { * "createdBy": "61de2c5fe1ba8c000175c2b2", * "createdAt": 1643443150345 * }, * "groupId": "61de2c5fe1ba8c000175c2b3", * "cooperateStatus": { * "value": "Valid", * "reason": "", * "lastUpdated": 1643443150345, * "modifiedBy": "18220595937" * }, * "cooperateValidStatus": { * "reason": "", * "lastUpdated": 0, * "modifiedBy": "" * }, * "cooperateInvalidStatus": { * "reason": "", * "lastUpdated": 0, * "modifiedBy": "" * }, * "owner": "wqef", * "expire": 9999999999999, * "apiServer": "https://finchat-mop-b.finogeeks.club", * "apmServer": "https://finchat-mop-b.finogeeks.club" * } * ] * }, * "errcode": "OK", * "error": "" * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func GetBindingsByAppId(c *gin.Context) { var ( traceCtx = apm.ApmClient().TraceContextFromGin(c) req = apiproto.GetBindingsByAppIdReq{} errRsp = make(map[string]interface{}) ) if err := c.BindQuery(&req); err != nil { log.Errorf("list bindings bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, errRsp) return } log.Infof("get bindings seq req:%+v", req) svr := service.NewBindingService() svr.GetBindingsByAppId(c, traceCtx, req) return } type GetLimitBindingListReq struct { OrganId string `form:"organId"` PageNo int `form:"pageNo"` PageSize int `form:"pageSize"` } type GetLimitBindingListRsp struct { Total int `json:"total"` List []GetLimitBindingListRspItem `json:"list"` } type GetLimitBindingListRspItem struct { BindingId string `json:"bindingId"` BindingName string `json:"bindingName"` BundleIdNum int `json:"bundleIdNum"` CoopStatus string `json:"coopStatus"` //合作状态 CreateTime int64 `json:"createTime"` //创建时间 ExpireTime int64 `json:"expireTime"` //过期时间 BundleInfos []entity.BundleInfo `json:"bundleInfos"` } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func GetLimitBindingList(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) req := GetLimitBindingListReq{} rsp := GetLimitBindingListRsp{ Total: 0, List: make([]GetLimitBindingListRspItem, 0), } if err := c.BindQuery(&req); err != nil { log.Errorf("GetLimitBindingList bind req error:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, rsp) return } if req.PageSize >= 100 || req.PageSize <= 0 { req.PageSize = 100 } //filter := bson.M{"groupId": req.OrganId} //sortFilter := []string{"-createdInfo.createdAt"} //binds := make([]model.Binding, 0) //t := db.NewTable(db.TableBinding) //total, err := t.GetSome(traceCtx, filter, sortFilter, req.PageSize, req.PageNo, &binds) svr := service.NewBindingService() binds, total, err := svr.GetBindingByGroupId(traceCtx, req.OrganId, req.PageSize, req.PageNo) if err != nil && !svr.NotFound(err) { log.Errorf("GetLimitBindingList get binding list error:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, rsp) return } rsp.Total = total for _, v := range binds { item := GetLimitBindingListRspItem{} item.BindingId = v.BindingID item.BindingName = v.Name item.CreateTime = v.CreatedInfo.CreatedAt / 1e3 item.CoopStatus = v.CooperateStatus.Value item.BundleInfos = v.BundleInfos item.BundleIdNum = len(v.BundleInfos) if v.Expire == MAX_EXPIRE_DATA { item.ExpireTime = 0 } else { item.ExpireTime = v.Expire } rsp.List = append(rsp.List, item) } utility.MakeLocRsp(c, http.StatusOK, utility.OK, rsp) return } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func GetBindingsByIds(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) bindingIds := c.Query("ids") if bindingIds == "" { log.Errorf("GetBindingsByIds binding id empty!") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_PARAM_ERR, gin.H{}) return } svr := service.NewBindingService() bindings, err := svr.GetBindingsByIds(traceCtx, strings.Split(bindingIds, ",")) if err != nil { log.Errorf("GetBindingsByIds err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, gin.H{}) return } utility.MakeLocRsp(c, http.StatusOK, utility.OK, gin.H{"list": bindings}) return } type GetBundleIdLimitHandRsp struct { LimitNum int `json:"limitNum"` HasUseNum int `json:"hasUseNum"` } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func BundlesLimit(c *gin.Context) { ctx := apm.ApmClient().TraceContextFromGin(c) svr := service.NewBindingService() rsp := GetBundleIdLimitHandRsp{} var statusCode string rsp.LimitNum, rsp.HasUseNum, statusCode = svr.BundleLimit(ctx, c) if statusCode != utility.OK { utility.MakeLocRsp(c, http.StatusInternalServerError, statusCode, gin.H{}) } else { utility.MakeLocRsp(c, http.StatusOK, utility.OK, rsp) } return } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func GetBundleIdLimitHand(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) errRsp := make(map[string]interface{}) //目前saas、private环境bundleId限制数量在license里面 rsp := GetBundleIdLimitHandRsp{} licenseInfo, err := hCaller.GetLicense(traceCtx) if err != nil { log.Errorf("GetBundleIdLimitHand get err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_LICENSE_SERVER_ERROR, errRsp) return } log.Infof("GetBundleIdLimitHand get license info:%+v", licenseInfo) developerID := c.Request.Header.Get("x-consumer-custom-id") log.Infof("GetBundleIdLimitHand account id:%s", developerID) groupInfo, err := hCaller.GetGroupInfoByUserId(traceCtx, developerID) if err != nil { log.Errorf("GetBundleIdLimitHand get group id err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_GET_GROUP_FAILED, errRsp) return } log.Infof("GetBundleIdLimitHand groupId:%s", groupInfo.GroupID) //校验bundingId的数量 svr := service.NewBindingService() bundleIdTotal, err := svr.GetBundleIdLimitHand(traceCtx, groupInfo.GroupID) if err != nil { log.Errorf("GetBundleIdLimitHand get bundleId count id err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_GET_GROUP_FAILED, errRsp) return } rsp.LimitNum = licenseInfo.CooAppCount * 2 rsp.HasUseNum = bundleIdTotal utility.MakeLocRsp(c, http.StatusOK, utility.OK, rsp) return } type GetSecretBySdkKeyHandReq struct { SdkKey string `form:"sdkKey"` } //根绝sdkKey获取secret func GetSecretBySdkKeyHand(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) req := GetSecretBySdkKeyHandReq{} rsp := make(map[string]string) if err := c.BindQuery(&req); err != nil { log.Errorf("GetSecretBySdkKeyHand bind error:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, rsp) return } if req.SdkKey == "" { log.Errorf("GetSecretBySdkKeyHand sdk key empty") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_SDKKEY_NOT, rsp) return } log.Infof("GetSecretBySdkKeyHand req:%+v", req) var secret string if utility.InArry(req.SdkKey, config.WhiteSDKArry) { log.Infof("GetSecretBySdkKeyHand in white list:%s", req.SdkKey) for _, v := range config.WhiteSDKList { if req.SdkKey == v.SDKKey { secret = v.SDKID } } rsp["secret"] = secret utility.MakeLocRsp(c, http.StatusOK, utility.OK, rsp) return } svr := service.NewBindingService() bind, err := svr.GetBindingBySdkKey(traceCtx, req.SdkKey) if err != nil { log.Errorf("GetSecretBySdkKeyHand db err:%s", err.Error()) if service.NotFound(err) { utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BIND_NOT_FOUND, gin.H{}) } else { utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, gin.H{}) } return } for _, v := range bind.BundleInfos { if v.SDKKey == req.SdkKey { secret = v.SDKID } } log.Infof("GetBindingIdBySdkKeyHand sdkKey:%s,result:%+v", req.SdkKey, bind) rsp["secret"] = secret utility.MakeLocRsp(c, http.StatusOK, utility.OK, rsp) } func GetOrganIdBySdkKey(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) rsp := make(map[string]interface{}) sdkKey := c.DefaultQuery("sdkKey", "") if sdkKey == "" { log.Errorf("GetOrganIdBySdkKey sdkKey empty") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, gin.H{}) return } log.Infof("GetOrganIdBySdkKey sdk key:%+v", sdkKey) if utility.InArry(sdkKey, config.WhiteSDKArry) { rsp["isWhite"] = true rsp["organId"] = "" utility.MakeLocRsp(c, http.StatusOK, utility.OK, rsp) return } svr := service.NewBindingService() result, err := svr.GetBindingBySdkKey(traceCtx, sdkKey) if err != nil { log.Errorf("GetOrganIdBySdkKey get binding info error:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_SERVICE_UNAVAILABLE, rsp) return } log.Infof("GetOrganIdBySdkKey sdkKey:%s,result:%+v", sdkKey, result) rsp["organId"] = "" rsp["isWhite"] = false utility.MakeLocRsp(c, http.StatusOK, utility.OK, rsp) return } type GetBindingInfoByIdHandReq struct { BindingId string `form:"bindingId"` } type GetBindingInfoByIdHandRsp struct { BindingID string `json:"bindingId"` Name string `json:"name"` CoopStatus string `json:"coopStatus"` GroupId string `json:"groupId"` } func GetBindingInfoByIdHand(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) req := GetBindingInfoByIdHandReq{} rsp := GetBindingInfoByIdHandRsp{} if err := c.BindQuery(&req); err != nil { log.Errorf("GetBindingInfoByIdHand bind error:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, rsp) return } if req.BindingId == "" { log.Errorf("GetBindingInfoByIdHand sdk key empty") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_SDKKEY_NOT, rsp) return } svr := service.NewBindingService() result, err := svr.GetInfo(traceCtx, req.BindingId) if err != nil && !config.GetConfig().IsHcc { log.Errorf("GetBindingInfoByIdHand get binding info error:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_SERVICE_UNAVAILABLE, rsp) return } if config.GetConfig().IsHcc { result.Name = config.BindingWhiteList.BindingList[0].Name } rsp.CoopStatus = result.CooperateStatus.Value rsp.BindingID = result.BindingID rsp.Name = result.Name rsp.GroupId = result.GroupID utility.MakeLocRsp(c, http.StatusOK, utility.OK, rsp) } type BundlesReq struct { PageSize int `form:"pageSize"` PageNo int `form:"pageNo"` SearchText string `form:"searchText"` SelectType int `form:"selectType"` //0:全部 1:启用 2:禁用 } /** * @api {POST} /api/v1/finstore/dev/bindings/creation [C/S][MOP]机构端应用管理创建应用 * @apiGroup Finclip App Manager * @apiVersion __API_VERSION__ * * @apiParam (RequestBody) {string} name 应用名 * @apiParam (RequestBody) {[]BundleInfo} bundleInfos bundid信息 * @apiParamExample {json} Request-Example: * { * "name": "应用名", * "owner":"所属企业", * "bundleInfos":[ * { * "bundleId":"jaogajigaigojagioagj", //bundle id * "remark":"备注" * }, * { * "bundleId":"jaogajigaigojagioagj", //bundle id * "remark":"备注" * } * ] * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ /** * @api {GET} /api/v1/mop/finstore/admin/bundle/list [C/S][MOP]获取bundleId列表 * @apiGroup Finclip App Manager * @apiVersion __API_VERSION__ * * @apiParam (Param) {int} [pageSize] 条数 * @apiParam (Param) {int} [pageNo] 当前页 * @apiParam (Param) {string} [searchText] 搜索bundleId * @apiParam (Param) {int} [selectType] 过滤类型 0:全部 1:可用 2:禁用 * @apiParamExample {URL} Request-Example: * /api/v1/mop/finstore/admin/bundle/list?pageNo=1&pageSize=100&searchType=0 * @apiSuccessExample {json} Success Status: * { * "list": [ * { * "SDKID": "0b2e431bca162a8a", * "SDKKey": "bFmSSsu7UCSbIWhwzCvbNnH0wV1QJzE3hdcwS5zRz5g=", * "bundleId": "autonpgdh", * "createdAccount": "admin", * "createdAt": 1653048845379, * "createdBy": "admin", * "isFirstCreate": true, * "remark": "ios", * "isForbidden":0 * } * ], * "total": 1 *} * HTTP/1.1 200 OK * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func Bundles(c *gin.Context) { ctx := apm.ApmClient().TraceContextFromGin(c) req := BundlesReq{} if err := c.BindQuery(&req); err != nil { log.Errorf("Bundles req bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, gin.H{}) return } log.Infof("Bundles req:%+v", req) svr := service.NewBindingService() total, bundleInfos, err := svr.ListAllBundleInfos(ctx, req.SearchText, req.SelectType, req.PageNo, req.PageSize) if err != nil { if svr.NotFound(err) { utility.MakeLocRsp(c, http.StatusOK, utility.OK, gin.H{}) return } } c.JSON(http.StatusOK, gin.H{ "total": total, "list": bundleInfos, }) return } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func CreateBundles(c *gin.Context) { var req service.CreateBundlesReq err := c.ShouldBindJSON(&req) if err != nil { log.Errorf("CreateBinding bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, gin.H{}) return } if len(req.List) == 0 { log.Warf("CreateBundles len list empty!") utility.MakeLocRsp(c, http.StatusOK, utility.OK, gin.H{}) return } req.DeveloperID = c.Request.Header.Get("X-Consumer-Custom-ID") ctx := apm.ApmClient().TraceContextFromGin(c) svr := service.NewBindingService() statusCode := svr.CreateBundles(ctx, c, req) if statusCode != utility.OK { utility.MakeLocRsp(c, http.StatusInternalServerError, statusCode, gin.H{}) } else { utility.MakeLocRsp(c, http.StatusCreated, utility.OK, gin.H{}) } } type BundleIsExistReq struct { List []string `json:"list"` } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func BundleIsExist(c *gin.Context) { var req BundleIsExistReq err := c.BindJSON(&req) if err != nil { log.Errorf("CreateBinding bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, gin.H{}) return } log.Infof("BundleIsExist req:%+v", req) if len(req.List) > 200 { log.Errorf("BundleIsExist req list over limit!") utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, gin.H{}) return } ctx := apm.ApmClient().TraceContextFromGin(c) svr := service.NewBindingService() existBundleIds, statusCode := svr.BundleIsExist(ctx, req.List) log.Errorf("existBundleIds", utility.InterfaceToJsonString(existBundleIds)) if statusCode != utility.OK { utility.MakeLocRsp(c, http.StatusInternalServerError, statusCode, gin.H{}) } else { c.JSON(http.StatusOK, gin.H{ "list": existBundleIds, }) } } type GetSdkKeyReq struct { AppId string `uri:"appId"` } type GetSdkKeyRsp struct { List []string `json:"list"` } func GetSdkKeyList(c *gin.Context) { traceCtx := apm.ApmClient().TraceContextFromGin(c) req := GetSdkKeyReq{} rsp := GetSdkKeyRsp{ List: make([]string, 0), } if err := c.BindUri(&req); err != nil { log.Errorf("AdminGetAppVerDetail bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, gin.H{}) return } svr := service.NewBindingService() binds, err := svr.GetAssBindsByAppId(traceCtx, req.AppId) if err != nil { if service.NotFound(err) { utility.MakeLocRsp(c, http.StatusOK, utility.OK, rsp) return } log.Errorf("GetAssBindsByAppId err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusInternalServerError, utility.FS_DB_ERR, gin.H{}) return } var sdkKeyListMap = make(map[string]bool, 0) for _, v := range binds { for _, sdkKeyInfo := range v.BundleInfos { if _, ok := sdkKeyListMap[sdkKeyInfo.SDKKey]; !ok { sdkKeyListMap[sdkKeyInfo.SDKKey] = true } } } for k, _ := range sdkKeyListMap { rsp.List = append(rsp.List, k) } utility.MakeLocRsp(c, http.StatusOK, utility.OK, rsp) return } /** * @api {POST} /api/v1/mop/finstore/admin/bundle/update/is_forbidden [C/S][MOP]运营端更新bundleId禁用状态 * @apiGroup Finclip App Manager * @apiVersion __API_VERSION__ * * @apiParam (RequestBody) {string} bundleId bundleId * @apiParam (RequestBody) {int} isForbidden 0:可用 1:禁用 * @apiParamExample {json} Request-Example: * { * "bundleId": "test111", * "isForbidden": 0 * } * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "", * "data": { * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func UpdateBundlesIsForbidden(c *gin.Context) { var req service.UpdateBundleIsForbiddenReq err := c.ShouldBindJSON(&req) if err != nil { log.Errorf("UpdateBundlesIsForbidden bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, gin.H{}) return } if req.BundleId == "" { log.Warf("UpdateBundlesIsForbidden BundleId empty!") utility.MakeLocRsp(c, http.StatusOK, utility.OK, gin.H{}) return } ctx := apm.ApmClient().TraceContextFromGin(c) svr := service.NewBindingService() statusCode := svr.UpdateBundleIsForbidden(ctx, req) if statusCode != utility.OK { utility.MakeLocRsp(c, http.StatusInternalServerError, statusCode, gin.H{}) } else { utility.MakeLocRsp(c, http.StatusOK, utility.OK, gin.H{}) } } /** * @api {POST} /api/v1/mop/finstore/admin/bundle/update/platform [C/S][MOP]运营端更新bundleId平台 * @apiGroup Finclip App Manager * @apiVersion __API_VERSION__ * * @apiParam (RequestBody) {string} bundleId bundleId * @apiParam (RequestBody) {int} platform 平台 * @apiParamExample {json} Request-Example: * { * "bundleId": "test111", * "platform": "ios" * } * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "", * "data": { * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ func UpdateBundlesPlatform(c *gin.Context) { var req service.UpdateBundlePlatformReq err := c.ShouldBindJSON(&req) if err != nil { log.Errorf("UpdateBundlesPlatform bind err:%s", err.Error()) utility.MakeLocRsp(c, http.StatusBadRequest, utility.FS_BAD_JSON, gin.H{}) return } if req.BundleId == "" { log.Warf("UpdateBundlesPlatform BundleId empty!") utility.MakeLocRsp(c, http.StatusOK, utility.OK, gin.H{}) return } ctx := apm.ApmClient().TraceContextFromGin(c) svr := service.NewBindingService() statusCode := svr.UpdateBundlesPlatform(ctx, req) if statusCode != utility.OK { utility.MakeLocRsp(c, http.StatusInternalServerError, statusCode, gin.H{}) } else { utility.MakeLocRsp(c, http.StatusOK, utility.OK, gin.H{}) } } /** * @api {GET} * @apiGroup Finclip App Manager * @apiSuccessExample {json} Success Status: * HTTP/1.1 200 OK * { * "errcode": "OK", * "error": "成功", * "data":{ * * } * } * @apiErrorExample Error Status: * HTTP/1.1 !=200 服务端异常 */ type AddBundleIdLimitNumHandRsp struct { AddAvailableLimitNum int `json:"addAvailableLimitNum"` AddAllLimitNum int `json:"addAllLimitNum"` } func AddBundleIdLimitNumConfig(c *gin.Context) { rsp := AddBundleIdLimitNumHandRsp{} rsp.AddAllLimitNum = config.GetConfig().AddALLBundleNum rsp.AddAvailableLimitNum = config.GetConfig().AddAvailableBundleNum utility.MakeLocRsp(c, http.StatusOK, utility.OK, rsp) return }