package wfclient import ( "encoding/base64" "encoding/json" "errors" "fmt" "net/http" "strconv" "strings" ) type Filter struct { GroupOp string `json:"groupOp"` Rules []*FilterField `json:"rules"` } type FilterField struct { Field string `json:"field"` Op string `json:"op"` Data string `json:"data"` } type CallbackArg struct { DefineId string InstanceId string DefineName string FormData string Choice string Executor string UserId string } type WFClient struct { endpoint string authorization string userId string username string token string domain string callbackMap map[string]func(CallbackArg) } var instance *WFClient = nil /** * @brief: single instance */ func Instance() *WFClient { if instance == nil { instance = &WFClient{} instance.endpoint = "" instance.authorization = "" instance.userId = "" instance.token = "" instance.callbackMap = make(map[string]func(CallbackArg)) HttpClientInstance().setRequestInterseptor(instance.wfReqInterseptor) } return instance } /** * @brief: init * @param1 endpoint: endpoint of wf service, do not end with /; such as http://wf.qianqiusoft.com * @param2 userId: user's id * @param3 username: username * @param4 token: token * @param5 domain: domain, its default value is qianqiusoft.com * @return1: information of error, nil if everything is all right */ func (w *WFClient) Init(endpoint, userId, username, token, domain string) error { if w.token == token && w.authorization != "" { fmt.Println("wfclient token", w.token, "does already exist, token is", w.authorization) return nil } var err error = nil w.endpoint = endpoint w.userId = userId w.authorization, err = w.createAuthorization(username, token, domain) w.token = token if err != nil { return err } else { return nil } } /** * @brief: add callback * @param1: key * @param2: callback */ func (w *WFClient) AddCallback(key string, cb func(CallbackArg)) { if _, ok := w.callbackMap[key]; !ok { w.callbackMap[key] = cb } else { fmt.Println("callback", key, "does already exist") } } /** * @brief: create or update the define, * @param1 defineId: id of define, if the define with id does already exist, update the define * @param2 defineName: name of define * @param3 defineDesc: description of define * @param4 diagram: diagram of define * @param5 formName: name of the form * @return1 information of error */ func (w *WFClient) CreateOrUpdateDefine(defineId, defineName, defineDesc, diagram, formName, tag, code string) ([]byte, error) { url := w.getFullUrl(fmt.Sprintf("api/wf_define/%s", defineId)) fmt.Println("----url:", url) params := make(map[string]string) params["define_id"] = defineId params["name"] = defineName params["descript"] = defineDesc params["data"] = diagram params["form"] = formName params["code"] = code params["tag"] = tag return HttpClientInstance().post(url, params, nil) } func (w *WFClient) FetchDefine(defineId string) ([]byte, error) { url := w.getFullUrl("api/wf_define/" + defineId) fmt.Println(url) return HttpClientInstance().get(url, nil, nil) } func (w *WFClient) FetchAllDefines() ([]byte, error) { url := w.getFullUrl("api/wf_define/all") return HttpClientInstance().get(url, nil, nil) } /** * @brief: get the flow define by tag * @param1 tag: tag of the define, split by , * @return1: content of response * @return2: information of error, nil if everything is all right */ func (w *WFClient) FetchDefinesByTag(tag string) ([]byte, error) { url := w.getFullUrl("api/wf_define/list/tag") params := make(map[string]string) params["tag"] = tag return HttpClientInstance().get(url, params, nil) } /** * @brief: get the flow design diagram * @param1 id: id of flow define * @return1: content of response * @return2: information of error, nil if everything is all right */ func (w *WFClient) FetchDesignDiagram(defineId string) ([]byte, error) { url := w.getFullUrl(fmt.Sprintf("api/wf_define/designer/%s", defineId)) return HttpClientInstance().get(url, nil, nil) } /** * @brief: create a wf instance * @param1 defineId: id of wf define * @param2 name: name of instance * @param3 formData: data to submit * @return1: content of response * @return2: error */ func (w *WFClient) CreateInstance(defineId, name, formData string) ([]byte, error) { url := w.getFullUrl("api/wf_instance") params := make(map[string]string) params["define_id"] = defineId params["name"] = name params["form_data"] = formData return HttpClientInstance().post(url, params, nil) } /** * @brief: run the wf instance * @param1 instanceId: id of instance * @param2 userId: approver id * @param3 choice: choice * @param4 options: options * @return1 content of response * @return2 error */ func (w *WFClient) Run(instanceId, userId, choice, options, nextStep string) ([]byte, error) { url := w.getFullUrl("api/wf_instance/run") params := make(map[string]string) params["instance_id"] = instanceId params["users"] = userId if choice != "" { params["choice"] = choice } if options != "" { params["opinion"] = options } if nextStep != "" { params["nextStep"] = nextStep } var RunRespInfo struct { DefineId string `json:"define_id"` InstanceId string `json:"instance_id"` DefineName string `json:"define_name"` Choice string `json:"choice"` FormData string `json:"form_data"` StepName string `json:"step_name"` ActorType string `json:"actor_type"` Executor string `json:"executor"` StartCallback string `json:"start_callback"` } bytess, err := HttpClientInstance().post(url, params, nil) if err != nil { return nil, err } err = json.Unmarshal(bytess, &RunRespInfo) if err != nil { return nil, err } fmt.Println("------------------------------------->121", RunRespInfo.StartCallback) callbacks := strings.Split(RunRespInfo.StartCallback, ",") for _, callbackKye := range callbacks { callback, ok := w.callbackMap[callbackKye] if ok { fmt.Println("------------------------------------->121") callback(CallbackArg{ DefineId: RunRespInfo.DefineId, InstanceId: RunRespInfo.InstanceId, DefineName: RunRespInfo.DefineName, FormData: RunRespInfo.FormData, Choice: RunRespInfo.Choice, Executor: RunRespInfo.Executor, UserId: w.userId, }) } } return []byte{}, nil } /** * @brief: pre the wf instance * @param1 instanceId: id of instance * @param2 choice: choice of step * @return1 content of response * @return2 error */ func (w *WFClient) PreRun(instanceId, choice string) ([]byte, error) { url := w.getFullUrl("api/wf_instance/prerun") params := make(map[string]string) params["instance_id"] = instanceId params["choice"] = choice return HttpClientInstance().post(url, params, nil) } /** * @brief: fetch my instances * @param1 page: page num, start from 1 * @param2 rows: count per page, its default value is 10000 * @return1: content of response * @return2: information of error */ func (w *WFClient) FetchMyInstances(page, rows int) ([]byte, error) { url := w.getFullUrl("/api/wf_instance/mime") params := make(map[string]string) params["page"] = strconv.FormatInt(int64(page), 10) params["pageSize"] = strconv.FormatInt(int64(rows), 10) return HttpClientInstance().get(url, params, nil) } /** * @brief: fetch current step of login user * @param1 instanceId: id of instance * @return1 content of response * @return2 error */ func (w *WFClient) FetchCurrentStepByLoginUser(instanceId string) ([]byte, error) { url := w.getFullUrl("/api/wf_instance/user/current") params := make(map[string]string) params["instance_id"] = instanceId return HttpClientInstance().get(url, params, nil) } /** * @brief: fetch current step of instance * @param1 instanceId: id of instance * @return1 content of response * @return2 error */ func (w *WFClient) FetchCurrentStep(instanceId string) ([]byte, error) { url := w.getFullUrl("/api/wf_instance/current") params := make(map[string]string) params["instance_id"] = instanceId return HttpClientInstance().get(url, params, nil) } /** * @brief: fetch my to do list * @param1 page: page num, start from 1 * @param2 rows: count per page, its default value is 10000 * @return1: content of response * @return2: information of error */ func (w *WFClient) FetchToDoList(page, rows int) ([]byte, error) { url := w.getFullUrl("/api/wf_instance/todo") params := make(map[string]string) params["page"] = strconv.FormatInt(int64(page), 10) params["pageSize"] = strconv.FormatInt(int64(rows), 10) return HttpClientInstance().get(url, params, nil) } /** * @brief: fetch my done list * @param1 page: page num, start from 1 * @param2 rows: count per page, its default value is 10000 * @return1: content of response * @return2: information of error */ func (w *WFClient) FetchDoneList(page, rows int) ([]byte, error) { url := w.getFullUrl("/api/wf_instance/done") params := make(map[string]string) params["page"] = strconv.FormatInt(int64(page), 10) params["pageSize"] = strconv.FormatInt(int64(rows), 10) return HttpClientInstance().get(url, params, nil) } func (w *WFClient) FetchWFINstances(page, rows int, filters, sidx, sord string) ([]byte, error) { url := w.getFullUrl("/api/wf_instance/list") fmt.Println("wf url: ", url) params := make(map[string]string) params["page"] = strconv.FormatInt(int64(page), 10) params["rows"] = strconv.FormatInt(int64(rows), 10) params["sidx"] = sidx params["sord"] = sord params["filters"] = filters return HttpClientInstance().get(url, params, nil) } /** * @brief: wf req interseptor * @param1 r: http req */ func (w *WFClient) wfReqInterseptor(r *http.Request) { //r.Header.Add("Authorization", w.authorization) fmt.Println("header add token", w.token) r.Header.Add("token", w.token) } /** * @brief: create the authorization by username, token and domain * @param2 username: username * @param3 token: token * @param4 domain: domain, its default value is qianqiusoft.com * @return1 authorization, such as Bearer adfeadfsdfsdffds * @return2 information of error, nil if everything is all right */ func (w *WFClient) createAuthorization(username, token, domain string) (string, error) { if username == "" || token == "" { return "", errors.New("username or token is empty") } if domain == "" { domain = "qianqiusoft.com" } w.username = username w.token = token w.domain = domain tstr := fmt.Sprintf("%s:%s:%s", username, token, domain) tbase64str := base64.StdEncoding.EncodeToString([]byte(tstr)) finalStr := "sso-auth-token:" + tbase64str return "Bearer " + base64.StdEncoding.EncodeToString([]byte(finalStr)), nil } /** * @brief: get full url * @param1 path: api path, such as /api/wf_instance/done * @return1 url with query params */ func (w *WFClient) getFullUrl(path string) string { path = strings.TrimLeft(path, "/") return fmt.Sprintf("%s/%s", w.endpoint, path) } //撤回 func (w *WFClient) Recall(definedId string) ([]byte, error) { url := w.getFullUrl("/api/wf_instance/recall") params := make(map[string]string) params["instance_id"] = definedId return HttpClientInstance().post(url, params, nil) }