client.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. package wfclient
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "encoding/xml"
  6. "errors"
  7. "fmt"
  8. "net/http"
  9. "strconv"
  10. "strings"
  11. "git.qianqiusoft.com/qianqiusoft/light-apiengine/config"
  12. "git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys"
  13. "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils"
  14. )
  15. type Filter struct {
  16. GroupOp string `json:"groupOp"`
  17. Rules []*FilterField `json:"rules"`
  18. }
  19. type FilterField struct {
  20. Field string `json:"field"`
  21. Op string `json:"op"`
  22. Data string `json:"data"`
  23. }
  24. type WFClient struct {
  25. endpoint string
  26. authorization string
  27. userId string
  28. username string
  29. token string
  30. domain string
  31. }
  32. var _wfendpoint = ""
  33. func init() {
  34. _wfendpoint = config.AppConfig.GetKey("wfendpoint")
  35. }
  36. /**
  37. * @brief: single instance
  38. */
  39. func NewWFClient(c *entitys.CtrlContext) *WFClient {
  40. tk, _ := c.Ctx.Get("token")
  41. token := tk.(*entitys.Token)
  42. instance := &WFClient{}
  43. instance.endpoint = _wfendpoint
  44. instance.authorization, _ = instance.createAuthorization(token.LoginID, token.AccessToken, token.Domain)
  45. instance.userId = token.UserId
  46. instance.token = token.AccessToken
  47. HttpClientInstance().setRequestInterseptor(instance.wfReqInterseptor)
  48. return instance
  49. }
  50. /**
  51. * @brief: init
  52. * @param1 endpoint: endpoint of wf service, do not end with /; such as http://wf.qianqiusoft.com
  53. * @param2 userId: user's id
  54. * @param3 username: username
  55. * @param4 token: token
  56. * @param5 domain: domain, its default value is qianqiusoft.com
  57. * @return1: information of error, nil if everything is all right
  58. */
  59. func (w *WFClient) Init(endpoint, userId, username, token, domain string) error {
  60. if w.token == token && w.authorization != "" {
  61. fmt.Println("wfclient token", w.token, "does already exist, token is", w.authorization)
  62. return nil
  63. }
  64. var err error = nil
  65. w.endpoint = endpoint
  66. w.userId = userId
  67. w.authorization, err = w.createAuthorization(username, token, domain)
  68. w.token = token
  69. if err != nil {
  70. return err
  71. } else {
  72. return nil
  73. }
  74. }
  75. /**
  76. * @brief: create or update the define,
  77. * @param1 defineId: id of define, if the define with id does already exist, update the define
  78. * @param2 defineName: name of define
  79. * @param3 defineDesc: description of define
  80. * @param4 diagram: diagram of define
  81. * @param5 formName: name of the form
  82. * @return1 information of error
  83. */
  84. func (w *WFClient) CreateOrUpdateDefine(defineId, defineName, defineDesc, diagram, formName, tag, code string) ([]byte, error) {
  85. if defineId == "" {
  86. defineId = utils.NewUUID()
  87. }
  88. url := w.getFullUrl(fmt.Sprintf("api/wf_define/%s", defineId))
  89. fmt.Println("----url:", url)
  90. params := make(map[string]string)
  91. params["define_id"] = defineId
  92. params["name"] = defineName
  93. params["descript"] = defineDesc
  94. params["data"] = diagram
  95. params["form"] = formName
  96. params["code"] = code
  97. params["tag"] = tag
  98. return HttpClientInstance().post(url, params, nil)
  99. }
  100. func (w *WFClient) FetchDefine(defineId string) ([]byte, error) {
  101. url := w.getFullUrl("api/wf_define/" + defineId)
  102. fmt.Println(url)
  103. return HttpClientInstance().get(url, nil, nil)
  104. }
  105. func (w *WFClient) FetchAllDefines() ([]byte, error) {
  106. url := w.getFullUrl("api/wf_define/all")
  107. return HttpClientInstance().get(url, nil, nil)
  108. }
  109. /**
  110. * @brief: get the flow define by tag
  111. * @param1 tag: tag of the define, split by ,
  112. * @return1: content of response
  113. * @return2: information of error, nil if everything is all right
  114. */
  115. func (w *WFClient) FetchDefinesByTag(tag string) ([]byte, error) {
  116. url := w.getFullUrl("api/wf_define/list/tag")
  117. params := make(map[string]string)
  118. params["tag"] = tag
  119. return HttpClientInstance().get(url, params, nil)
  120. }
  121. /**
  122. * @brief: get the flow design diagram
  123. * @param1 id: id of flow define
  124. * @return1: content of response
  125. * @return2: information of error, nil if everything is all right
  126. */
  127. func (w *WFClient) FetchDesignDiagram(defineId string) ([]byte, error) {
  128. url := w.getFullUrl(fmt.Sprintf("api/wf_define/designer/%s", defineId))
  129. return HttpClientInstance().get(url, nil, nil)
  130. }
  131. /**
  132. * @brief: create a wf instance
  133. * @param1 defineId: id of wf define
  134. * @param2 name: name of instance
  135. * @param3 formData: data to submit
  136. * @return1: content of response
  137. * @return2: error
  138. */
  139. func (w *WFClient) CreateInstance(defineId, name, formData string) ([]byte, error) {
  140. url := w.getFullUrl("api/wf_instance")
  141. params := make(map[string]string)
  142. params["define_id"] = defineId
  143. params["name"] = name
  144. params["form_data"] = formData
  145. return HttpClientInstance().post(url, params, nil)
  146. }
  147. // 更新流程实例表单
  148. func (w *WFClient) UpdateInstanceForm(instanceId, formData string) ([]byte, error) {
  149. url := w.getFullUrl("api/wf_instance/updateFormData")
  150. params := make(map[string]string)
  151. params["instance_id"] = instanceId
  152. params["form_data"] = formData
  153. return HttpClientInstance().post(url, params, nil)
  154. }
  155. type Choice struct {
  156. XMLName xml.Name `xml:"choice"json:"-"`
  157. Name string `json:"name"xml:"name"`
  158. Trans Transition `json:"trans"xml:"transition"`
  159. }
  160. type Transition struct {
  161. XMLName xml.Name `xml:"transition"json:"-"`
  162. Name string `json:"name"xml:"name"`
  163. To string `json:"to"xml:"to"`
  164. Points string `json:"-"xml:"points"`
  165. Conditions []*Condition `json:"conditions,omitempty"`
  166. Callback string `json:"callback"xml:"callback"`
  167. }
  168. type Condition struct {
  169. Operator string `json:"operator"xml:"operator"`
  170. DataKey string `json:"data_key"xml:"data_key"`
  171. Value string `json:"value"xml:"value"`
  172. Logic string `json:"logic"xml:"logic"`
  173. }
  174. /**
  175. * @brief: run the wf instance
  176. * @param1 instanceId: id of instance
  177. * @param2 userId: approver id
  178. * @param3 choice: choice
  179. * @param4 options: options
  180. * @return1 content of response
  181. * @return2 error
  182. */
  183. func (w *WFClient) Run(instanceId, userId, choice, options, nextStep string, c *entitys.CtrlContext) ([]byte, error) {
  184. url := w.getFullUrl("api/wf_instance/run")
  185. params := make(map[string]string)
  186. params["instance_id"] = instanceId
  187. params["users"] = userId
  188. if choice != "" {
  189. params["choice"] = choice
  190. }
  191. if options != "" {
  192. params["opinion"] = options
  193. }
  194. if nextStep != "" {
  195. params["nextStep"] = nextStep
  196. }
  197. var RunRespInfo struct {
  198. DefineId string `json:"define_id"`
  199. InstanceId string `json:"instance_id"`
  200. DefineName string `json:"define_name"`
  201. InstanceName string `json:"instance_name"`
  202. Choices []*Choice `json:"choices"`
  203. Transition *Transition `json:"transition"`
  204. StepType string `json:"step_type"`
  205. FormData string `json:"form_data"`
  206. StepName string `json:"step_name"`
  207. ActorType string `json:"actor_type"`
  208. Executor string `json:"executor"`
  209. StartCallback string `json:"start_callback"`
  210. }
  211. bytess, err := HttpClientInstance().post(url, params, nil)
  212. if err != nil {
  213. return nil, err
  214. }
  215. //fmt.Println("------------->>>>>--------", string(bytess))
  216. err = json.Unmarshal(bytess, &RunRespInfo)
  217. if err != nil {
  218. return nil, err
  219. }
  220. fmt.Println("------------------------------------->121", RunRespInfo.StartCallback)
  221. // 节点回调
  222. callbacks := strings.Split(RunRespInfo.StartCallback, ",")
  223. for _, callbackKye := range callbacks {
  224. callWFCallback(callbackKye, &CallbackArg{
  225. DefineId: RunRespInfo.DefineId,
  226. InstanceId: RunRespInfo.InstanceId,
  227. DefineName: RunRespInfo.DefineName,
  228. InstanceName: RunRespInfo.InstanceName,
  229. FormData: RunRespInfo.FormData,
  230. Choice: choice,
  231. Executor: RunRespInfo.Executor,
  232. UserId: w.userId,
  233. Context: c,
  234. })
  235. }
  236. // 连线回调
  237. linkCallbacks := []string{}
  238. if RunRespInfo.StepType == "begin" || RunRespInfo.StepType == "normal" {
  239. linkCallbacks = strings.Split(RunRespInfo.Transition.Callback, ",")
  240. } else {
  241. for _, c := range RunRespInfo.Choices {
  242. if c.Name == choice {
  243. linkCallbacks = strings.Split(c.Trans.Callback, ",")
  244. }
  245. }
  246. }
  247. for _, callbackKye := range linkCallbacks {
  248. callWFCallback(callbackKye, &CallbackArg{
  249. DefineId: RunRespInfo.DefineId,
  250. InstanceId: RunRespInfo.InstanceId,
  251. DefineName: RunRespInfo.DefineName,
  252. InstanceName: RunRespInfo.InstanceName,
  253. FormData: RunRespInfo.FormData,
  254. Choice: choice,
  255. Executor: RunRespInfo.Executor,
  256. UserId: w.userId,
  257. Context: c,
  258. })
  259. }
  260. return []byte{}, nil
  261. }
  262. /**
  263. * @brief: run the wf instance
  264. * @param1 instanceId: id of instance
  265. * @param2 userId: approver id
  266. * @param3 choice: choice
  267. * @param4 options: options
  268. * @return1 content of response
  269. * @return2 error
  270. */
  271. func (w *WFClient) NewStep(instanceId, userId, choice, options, nextStep string, c *entitys.CtrlContext) ([]byte, error) {
  272. url := w.getFullUrl("api/wf_instance/newstep")
  273. params := make(map[string]string)
  274. params["instance_id"] = instanceId
  275. params["users"] = userId
  276. if choice != "" {
  277. params["choice"] = choice
  278. }
  279. if options != "" {
  280. params["opinion"] = options
  281. }
  282. if nextStep != "" {
  283. params["nextStep"] = nextStep
  284. }
  285. bytess, err := HttpClientInstance().post(url, params, nil)
  286. if err != nil {
  287. return nil, err
  288. }
  289. return bytess, err
  290. }
  291. /**
  292. * @brief: pre the wf instance
  293. * @param1 instanceId: id of instance
  294. * @param2 choice: choice of step
  295. * @return1 content of response
  296. * @return2 error
  297. */
  298. func (w *WFClient) PreRun(instanceId, choice string) ([]byte, error) {
  299. url := w.getFullUrl("api/wf_instance/prerun")
  300. params := make(map[string]string)
  301. params["instance_id"] = instanceId
  302. params["choice"] = choice
  303. return HttpClientInstance().post(url, params, nil)
  304. }
  305. /**
  306. * @brief: fetch my instances
  307. * @param1 page: page num, start from 1
  308. * @param2 rows: count per page, its default value is 10000
  309. * @return1: content of response
  310. * @return2: information of error
  311. */
  312. func (w *WFClient) FetchMyInstances(page, rows int) ([]byte, error) {
  313. url := w.getFullUrl("/api/wf_instance/mime")
  314. params := make(map[string]string)
  315. params["page"] = strconv.FormatInt(int64(page), 10)
  316. params["pageSize"] = strconv.FormatInt(int64(rows), 10)
  317. return HttpClientInstance().get(url, params, nil)
  318. }
  319. /**
  320. * @brief: fetch current step of login user
  321. * @param1 instanceId: id of instance
  322. * @return1 content of response
  323. * @return2 error
  324. */
  325. func (w *WFClient) FetchCurrentStepByLoginUser(instanceId string) ([]byte, error) {
  326. url := w.getFullUrl("/api/wf_instance/user/current")
  327. params := make(map[string]string)
  328. params["instance_id"] = instanceId
  329. return HttpClientInstance().get(url, params, nil)
  330. }
  331. /**
  332. * @brief: fetch current step of instance
  333. * @param1 instanceId: id of instance
  334. * @return1 content of response
  335. * @return2 error
  336. */
  337. func (w *WFClient) FetchCurrentStep(instanceId string) ([]byte, error) {
  338. url := w.getFullUrl("/api/wf_instance/current")
  339. params := make(map[string]string)
  340. params["instance_id"] = instanceId
  341. return HttpClientInstance().get(url, params, nil)
  342. }
  343. /**
  344. * @brief: fetch my to do list
  345. * @param1 page: page num, start from 1
  346. * @param2 rows: count per page, its default value is 10000
  347. * @return1: content of response
  348. * @return2: information of error
  349. */
  350. func (w *WFClient) FetchToDoList(page, rows int) ([]byte, error) {
  351. url := w.getFullUrl("/api/wf_instance/todo")
  352. params := make(map[string]string)
  353. params["page"] = strconv.FormatInt(int64(page), 10)
  354. params["pageSize"] = strconv.FormatInt(int64(rows), 10)
  355. return HttpClientInstance().get(url, params, nil)
  356. }
  357. /**
  358. * @brief: fetch my done list
  359. * @param1 page: page num, start from 1
  360. * @param2 rows: count per page, its default value is 10000
  361. * @return1: content of response
  362. * @return2: information of error
  363. */
  364. func (w *WFClient) FetchDoneList(page, rows int) ([]byte, error) {
  365. url := w.getFullUrl("/api/wf_instance/done")
  366. params := make(map[string]string)
  367. params["page"] = strconv.FormatInt(int64(page), 10)
  368. params["pageSize"] = strconv.FormatInt(int64(rows), 10)
  369. return HttpClientInstance().get(url, params, nil)
  370. }
  371. func (w *WFClient) FetchWFINstances(page, rows int, filters, sidx, sord string) ([]byte, error) {
  372. url := w.getFullUrl("/api/wf_instance/list")
  373. fmt.Println("wf url: ", url)
  374. params := make(map[string]string)
  375. params["page"] = strconv.FormatInt(int64(page), 10)
  376. params["rows"] = strconv.FormatInt(int64(rows), 10)
  377. params["sidx"] = sidx
  378. params["sord"] = sord
  379. params["filters"] = filters
  380. return HttpClientInstance().get(url, params, nil)
  381. }
  382. /**
  383. * @brief: wf req interseptor
  384. * @param1 r: http req
  385. */
  386. func (w *WFClient) wfReqInterseptor(r *http.Request) {
  387. //r.Header.Add("Authorization", w.authorization)
  388. fmt.Println("header add token", w.token)
  389. r.Header.Add("token", w.token)
  390. }
  391. /**
  392. * @brief: create the authorization by username, token and domain
  393. * @param2 username: username
  394. * @param3 token: token
  395. * @param4 domain: domain, its default value is qianqiusoft.com
  396. * @return1 authorization, such as Bearer adfeadfsdfsdffds
  397. * @return2 information of error, nil if everything is all right
  398. */
  399. func (w *WFClient) createAuthorization(username, token, domain string) (string, error) {
  400. if username == "" || token == "" {
  401. return "", errors.New("username or token is empty")
  402. }
  403. if domain == "" {
  404. domain = "qianqiusoft.com"
  405. }
  406. w.username = username
  407. w.token = token
  408. w.domain = domain
  409. tstr := fmt.Sprintf("%s:%s:%s", username, token, domain)
  410. tbase64str := base64.StdEncoding.EncodeToString([]byte(tstr))
  411. finalStr := "sso-auth-token:" + tbase64str
  412. return "Bearer " + base64.StdEncoding.EncodeToString([]byte(finalStr)), nil
  413. }
  414. /**
  415. * @brief: get full url
  416. * @param1 path: api path, such as /api/wf_instance/done
  417. * @return1 url with query params
  418. */
  419. func (w *WFClient) getFullUrl(path string) string {
  420. path = strings.TrimLeft(path, "/")
  421. return fmt.Sprintf("%s/%s", w.endpoint, path)
  422. }
  423. //撤回
  424. func (w *WFClient) Recall(definedId string) ([]byte, error) {
  425. url := w.getFullUrl("/api/wf_instance/recall")
  426. params := make(map[string]string)
  427. params["instance_id"] = definedId
  428. return HttpClientInstance().post(url, params, nil)
  429. }
  430. //终止
  431. func (w *WFClient) Interrupt(definedId string, formData map[string]interface{}, c *entitys.CtrlContext) ([]byte, error) {
  432. url := w.getFullUrl("/api/wf_instance/interrupt")
  433. params := make(map[string]string)
  434. params["instance_id"] = definedId
  435. var RunRespInfo struct {
  436. DefineId string `json:"define_id"`
  437. InstanceId string `json:"instance_id"`
  438. DefineName string `json:"define_name"`
  439. InstanceName string `json:"instance_name"`
  440. Choices []*Choice `json:"choices"`
  441. Transition *Transition `json:"transition"`
  442. StepType string `json:"step_type"`
  443. FormData string `json:"form_data"`
  444. StepName string `json:"step_name"`
  445. ActorType string `json:"actor_type"`
  446. Executor string `json:"executor"`
  447. StartCallback string `json:"start_callback"`
  448. }
  449. bytess, err := HttpClientInstance().post(url, params, nil)
  450. if err != nil {
  451. return nil, err
  452. }
  453. callWFCallback("interrupt", &CallbackArg{
  454. DefineId: RunRespInfo.DefineId,
  455. InstanceId: definedId,
  456. DefineName: RunRespInfo.DefineName,
  457. InstanceName: RunRespInfo.InstanceName,
  458. FormData: formData["form_data"].(string),
  459. Executor: RunRespInfo.Executor,
  460. UserId: w.userId,
  461. Context: c,
  462. })
  463. return bytess, err
  464. }
  465. //同步修复回调
  466. func (w *WFClient) RepairSync(definedId string, formData map[string]interface{}, c *entitys.CtrlContext) ([]byte, error) {
  467. var RunRespInfo struct {
  468. DefineId string `json:"define_id"`
  469. InstanceId string `json:"instance_id"`
  470. DefineName string `json:"define_name"`
  471. InstanceName string `json:"instance_name"`
  472. Choices []*Choice `json:"choices"`
  473. Transition *Transition `json:"transition"`
  474. StepType string `json:"step_type"`
  475. FormData string `json:"form_data"`
  476. StepName string `json:"step_name"`
  477. ActorType string `json:"actor_type"`
  478. Executor string `json:"executor"`
  479. StartCallback string `json:"start_callback"`
  480. }
  481. callWFCallback("repairSync", &CallbackArg{
  482. DefineId: RunRespInfo.DefineId,
  483. InstanceId: definedId,
  484. DefineName: RunRespInfo.DefineName,
  485. InstanceName: RunRespInfo.InstanceName,
  486. FormData: formData["form_data"].(string),
  487. Executor: RunRespInfo.Executor,
  488. UserId: w.userId,
  489. Context: c,
  490. })
  491. return []byte{}, nil
  492. }
  493. //撤回
  494. func (w *WFClient) Delete(definedId string) ([]byte, error) {
  495. url := w.getFullUrl("/api/wf_define/delete")
  496. params := make(map[string]string)
  497. params["define_id"] = definedId
  498. return HttpClientInstance().post(url, params, nil)
  499. }