base_from_smm_http.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. package services
  2. import (
  3. "encoding/json"
  4. "eta/eta_index_lib/models"
  5. "eta/eta_index_lib/services/alarm_msg"
  6. "eta/eta_index_lib/utils"
  7. "fmt"
  8. "io/ioutil"
  9. netHttp "net/http"
  10. "strings"
  11. "time"
  12. )
  13. var (
  14. BridgeApiZhongJiIndexDataUrl = "/api/index_data/zhongji/smm/data" // 获取指标数据API
  15. BridgeApiZhongJiIndexListUrl = "/api/index_data/zhongji/smm/list" // 获取指标列表API
  16. )
  17. // Data is a struct that represents the data field in the JSON string
  18. type Data struct {
  19. Date string `json:"date"`
  20. Value string `json:"value"`
  21. Create string `json:"create"`
  22. }
  23. // Quota is a struct that represents the quota information in the JSON string
  24. type Quota struct {
  25. QuotaID string `json:"quota_id"`
  26. QuotaName string `json:"quota_name"`
  27. Unit string `json:"unit"`
  28. Frequency string `json:"frequency"`
  29. ValueType string `json:"value_type"`
  30. Precision int `json:"precision"`
  31. PermState int `json:"perm_state"`
  32. Data []Data `json:"data"`
  33. }
  34. // Response is a struct that represents the whole JSON string
  35. type SmmResponse struct {
  36. Code int `json:"code"`
  37. Msg string `json:"msg"`
  38. Quota []Quota `json:"data"`
  39. }
  40. type SmmResp struct {
  41. Code int `json:"code"`
  42. Msg string `json:"msg"`
  43. Data SmmResponse `json:"data"`
  44. }
  45. // smmPostCurl post请求同花顺接口
  46. //func smmPostCurl(urlStr string, dataMap map[string]io.Reader, num int, token string) (body []byte, err error, errMsg string) {
  47. // logMsg := ``
  48. // defer func() {
  49. // if err != nil {
  50. // if logMsg != `` {
  51. // errMsg = logMsg
  52. // go alarm_msg.SendAlarmMsg("post请求SMM接口失败,ERR:"+err.Error()+";errMsg:"+errMsg, 3)
  53. // }
  54. // }
  55. // }()
  56. // // 创建一个新的buffer,用于存储请求体
  57. // var reqBody bytes.Buffer
  58. // writer := multipart.NewWriter(&reqBody)
  59. //
  60. // // 添加Form-data参数
  61. // for key, value := range dataMap {
  62. // part, err := writer.CreateFormFile(key, key)
  63. // if err != nil {
  64. // fmt.Println("Error creating form file:", err)
  65. // return
  66. // }
  67. // _, err = io.Copy(part, value)
  68. // if err != nil {
  69. // fmt.Println("Error copying file content:", err)
  70. // return
  71. // }
  72. // }
  73. //
  74. // // 关闭multipart writer
  75. // writer.Close()
  76. //
  77. // // 发送POST请求
  78. // req, err := netHttp.NewRequest("POST", urlStr, &reqBody)
  79. // if err != nil {
  80. // fmt.Println("Error creating request:", err)
  81. // return
  82. // }
  83. //
  84. // req.Header.Set("Content-Type", writer.FormDataContentType())
  85. //
  86. // client := &netHttp.Client{}
  87. // resp, err := client.Do(req)
  88. // if err != nil {
  89. // fmt.Println("Error sending request:", err)
  90. // return
  91. // }
  92. // defer resp.Body.Close()
  93. //
  94. // // 处理响应
  95. // fmt.Println("Response Status:", resp.Status)
  96. //
  97. // body, err = ioutil.ReadAll(resp.Body)
  98. // if err != nil {
  99. // fmt.Println("Error reading response body:", err)
  100. // return
  101. // }
  102. // utils.FileLog.Info("SMM刷新token:" + string(body))
  103. //
  104. // var response SmmResponse
  105. // err = json.Unmarshal(body, &response)
  106. // if err != nil {
  107. // utils.FileLog.Info("post Err:", err.Error(), ";url:", urlStr, ";response:", string(body))
  108. // err = errors.New("Unmarshal Err:" + err.Error())
  109. // return
  110. // }
  111. // utils.FileLog.Info(fmt.Sprint("post request url:", urlStr, ";token:", token, ";response:", string(body)))
  112. // logMsg = fmt.Sprint("post request url:", urlStr, ";token:", token, ";response:", string(body))
  113. //
  114. // //如果是token失效,同时只是第一次请求(没有尝试强制刷新token,那么重新请求)
  115. // if utils.InArrayByInt([]int{-10020001, -10020002}, int(response.Code)) && num <= 0 {
  116. // //token失效
  117. // token, err = refreshSmmAccessToken()
  118. // if err != nil {
  119. // return
  120. // }
  121. // num++
  122. // return smmPostCurl(urlStr, dataMap, num, token)
  123. // } else if response.Code != 0 {
  124. // utils.FileLog.Info(fmt.Sprint("post data err:", response.Msg, ";url:", urlStr, ";response:", string(body)))
  125. // err = errors.New(response.Msg)
  126. // return
  127. // }
  128. //
  129. // return
  130. //}
  131. // GetSmmAccessToken 获取accessToken
  132. //func GetSmmAccessToken(isRefresh bool) (token string, err error) {
  133. // defer func() {
  134. // if err != nil {
  135. // go alarm_msg.SendAlarmMsg("获取SMM的token失败,ERR:"+err.Error(), 3)
  136. // }
  137. // }()
  138. // redisKey := utils.CACHE_EDB_SMM_SERVER_TOKEN
  139. // token, redisErr := utils.Rc.RedisString(redisKey)
  140. // //如果从redis中accessToken 获取失败或者token为空了,再或者需要强制刷新了,那么重新获取accessToken
  141. // if redisErr != nil || token == `` || isRefresh {
  142. // token, _ = refreshSmmAccessToken()
  143. // return
  144. // }
  145. // return
  146. //}
  147. // refreshSmmAccessToken 强制刷新获取accessToken
  148. //func refreshSmmAccessToken() (token string, err error) {
  149. // defer func() {
  150. // if err != nil {
  151. // go alarm_msg.SendAlarmMsg("刷新SMM的token失败;ERR:"+err.Error(), 3)
  152. // }
  153. // }()
  154. // tokenInfo, tmpErr := getSmmAccessToken()
  155. // if tmpErr != nil {
  156. // err = tmpErr
  157. // return
  158. // }
  159. // token = tokenInfo.Token
  160. //
  161. // //token存入redis
  162. // redisKey := utils.CACHE_EDB_SMM_SERVER_TOKEN
  163. // err = utils.Rc.Put(redisKey, token, time.Hour*24*7)
  164. // if err != nil {
  165. // err = fmt.Errorf("获取SMM的token成功;SMM token存入redis失败,ERR:%s", err.Error())
  166. // return
  167. // }
  168. // return
  169. //}
  170. type GetSmmTokenResp struct {
  171. Code int `json:"code"`
  172. Msg string `json:"msg"`
  173. Data SmmTokenData `json:"data"`
  174. }
  175. type SmmTokenData struct {
  176. Token string `json:"token"`
  177. }
  178. // getSmmAccessToken token内部请求接口
  179. //func getSmmAccessToken() (tokenData SmmTokenData, err error) {
  180. // defer func() {
  181. // if err != nil {
  182. // go alarm_msg.SendAlarmMsg("更新SMM的token失败;ERR:"+err.Error(), 3)
  183. // }
  184. // }()
  185. //
  186. // url := "https://datapro-api.smm.cn/dapi/user/auth"
  187. //
  188. // // 准备Form-data参数
  189. // values := map[string]io.Reader{
  190. // "user_name": strings.NewReader("18815284804"),
  191. // "password": strings.NewReader(utils.MD5("huangcf@cbnb.com.cn")),
  192. // "source": strings.NewReader("datapro"),
  193. // }
  194. //
  195. // // 创建一个新的buffer,用于存储请求体
  196. // var body bytes.Buffer
  197. // writer := multipart.NewWriter(&body)
  198. //
  199. // // 添加Form-data参数
  200. // for key, value := range values {
  201. // part, err := writer.CreateFormFile(key, key)
  202. // if err != nil {
  203. // fmt.Println("Error creating form file:", err)
  204. // return
  205. // }
  206. // _, err = io.Copy(part, value)
  207. // if err != nil {
  208. // fmt.Println("Error copying file content:", err)
  209. // return
  210. // }
  211. // }
  212. //
  213. // // 关闭multipart writer
  214. // writer.Close()
  215. //
  216. // // 发送POST请求
  217. // req, err := netHttp.NewRequest("POST", url, &body)
  218. // if err != nil {
  219. // fmt.Println("Error creating request:", err)
  220. // return
  221. // }
  222. //
  223. // req.Header.Set("Content-Type", writer.FormDataContentType())
  224. //
  225. // client := &netHttp.Client{}
  226. // resp, err := client.Do(req)
  227. // if err != nil {
  228. // fmt.Println("Error sending request:", err)
  229. // return
  230. // }
  231. // defer resp.Body.Close()
  232. //
  233. // // 处理响应
  234. // fmt.Println("Response Status:", resp.Status)
  235. //
  236. // bodyContent, err := ioutil.ReadAll(resp.Body)
  237. // if err != nil {
  238. // fmt.Println("Error reading response body:", err)
  239. // return
  240. // }
  241. // utils.FileLog.Info("SMM刷新token:" + string(bodyContent))
  242. //
  243. // var tokenResp GetSmmTokenResp
  244. // err = json.Unmarshal(bodyContent, &tokenResp)
  245. // if err != nil {
  246. // err = errors.New("Unmarshal Err:" + err.Error())
  247. // return
  248. // }
  249. // if tokenResp.Code != 0 {
  250. // err = errors.New("getAccessToken err:" + tokenResp.Msg)
  251. // return
  252. // }
  253. // tokenData = tokenResp.Data
  254. //
  255. // return
  256. //}
  257. // GetSmmNewIndexFromBridge 从桥接服务获取指标
  258. func GetSmmNewIndexFromBridge(edbCode string) (indexDataList []models.BaseFromSmmDataList, err error) {
  259. defer func() {
  260. if err != nil {
  261. tips := fmt.Sprintf("桥接服务-获取SMM指标失败, err: %s", err.Error())
  262. utils.FileLog.Info(tips)
  263. go alarm_msg.SendAlarmMsg(tips, 3)
  264. }
  265. }()
  266. url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiZhongJiIndexDataUrl)
  267. param := models.BridgeZhongJiIndexDataParams{EdbCode: edbCode}
  268. data, e := json.Marshal(param)
  269. if e != nil {
  270. err = fmt.Errorf("data json marshal err: %s", e.Error())
  271. return
  272. }
  273. body := ioutil.NopCloser(strings.NewReader(string(data)))
  274. client := &netHttp.Client{}
  275. req, e := netHttp.NewRequest("POST", url, body)
  276. if e != nil {
  277. err = fmt.Errorf("http create request err: %s", e.Error())
  278. return
  279. }
  280. checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
  281. contentType := "application/json;charset=utf-8"
  282. req.Header.Set("Content-Type", contentType)
  283. req.Header.Set("Authorization", checkToken)
  284. resp, e := client.Do(req)
  285. if e != nil {
  286. err = fmt.Errorf("http client do err: %s", e.Error())
  287. return
  288. }
  289. defer func() {
  290. _ = resp.Body.Close()
  291. }()
  292. b, e := ioutil.ReadAll(resp.Body)
  293. if e != nil {
  294. err = fmt.Errorf("resp body read err: %s", e.Error())
  295. return
  296. }
  297. if len(b) == 0 {
  298. err = fmt.Errorf("resp body is empty")
  299. return
  300. }
  301. // 生产环境解密
  302. if utils.RunMode == "release" {
  303. str := string(b)
  304. str = strings.Trim(str, `"`)
  305. b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
  306. }
  307. result := new(SmmResp)
  308. if e = json.Unmarshal(b, &result); e != nil {
  309. err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
  310. return
  311. }
  312. if result.Code != 200 {
  313. err = fmt.Errorf("result: %s", string(b))
  314. return
  315. }
  316. dataList := make([]models.BaseFromSmmDataList, 0)
  317. for _, quota := range result.Data.Quota {
  318. var dataListItem models.BaseFromSmmDataList
  319. dataListItem.IndexCode = quota.QuotaID
  320. for _, v := range quota.Data {
  321. dataItem := new(models.BaseFromSmmData)
  322. dataItem.IndexCode = quota.QuotaID
  323. dataItem.DataTime = v.Date
  324. dataItem.Value = v.Value
  325. createTime, e := time.Parse(utils.FormatDateTime, v.Create)
  326. if e != nil {
  327. err = fmt.Errorf("time parse err: %s", e.Error())
  328. return
  329. }
  330. dataItem.CreateTime = createTime
  331. dataItem.ModifyTime = createTime
  332. currentDate, _ := time.ParseInLocation(utils.FormatDate, v.Date, time.Local)
  333. timestamp := currentDate.UnixNano() / 1e6
  334. dataItem.DataTimestamp = timestamp
  335. dataListItem.Data = append(dataListItem.Data, dataItem)
  336. }
  337. dataList = append(dataList, dataListItem)
  338. }
  339. indexDataList = dataList
  340. return
  341. }
  342. // GetSmmNewIndexListFromBridge 从桥接服务获取指标列表
  343. func GetSmmNewIndexListFromBridge(params models.BridgeZhongJiIndexListParams) (indexList []*models.BaseFromSmmIndex, err error) {
  344. defer func() {
  345. if err != nil {
  346. tips := fmt.Sprintf("桥接服务-获取SMM指标失败, err: %s", err.Error())
  347. utils.FileLog.Info(tips)
  348. go alarm_msg.SendAlarmMsg(tips, 3)
  349. }
  350. }()
  351. url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiZhongJiIndexListUrl)
  352. data, e := json.Marshal(params)
  353. if e != nil {
  354. err = fmt.Errorf("data json marshal err: %s", e.Error())
  355. return
  356. }
  357. body := ioutil.NopCloser(strings.NewReader(string(data)))
  358. client := &netHttp.Client{}
  359. req, e := netHttp.NewRequest("POST", url, body)
  360. if e != nil {
  361. err = fmt.Errorf("http create request err: %s", e.Error())
  362. return
  363. }
  364. checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
  365. contentType := "application/json;charset=utf-8"
  366. req.Header.Set("Content-Type", contentType)
  367. req.Header.Set("Authorization", checkToken)
  368. resp, e := client.Do(req)
  369. if e != nil {
  370. err = fmt.Errorf("http client do err: %s", e.Error())
  371. return
  372. }
  373. defer func() {
  374. _ = resp.Body.Close()
  375. }()
  376. b, e := ioutil.ReadAll(resp.Body)
  377. if e != nil {
  378. err = fmt.Errorf("resp body read err: %s", e.Error())
  379. return
  380. }
  381. if len(b) == 0 {
  382. err = fmt.Errorf("resp body is empty")
  383. return
  384. }
  385. // 生产环境解密
  386. if utils.RunMode == "release" {
  387. str := string(b)
  388. str = strings.Trim(str, `"`)
  389. b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
  390. }
  391. result := new(models.SmmListResp)
  392. if e = json.Unmarshal(b, &result); e != nil {
  393. err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
  394. return
  395. }
  396. if result.Code != 200 {
  397. err = fmt.Errorf("result: %s", string(b))
  398. return
  399. }
  400. for _, v := range result.Data.Data.Data {
  401. typeList := strings.Split(v.TypeAll, ";")
  402. item := new(models.BaseFromSmmIndex)
  403. item.IndexCode = v.QuotaID
  404. item.IndexName = v.QuotaName
  405. item.Frequency = v.Frequency
  406. item.StartDate = v.DataStart
  407. item.EndDate = v.DataEnd
  408. item.Name = v.TypeName
  409. item.CreateTime = time.Now()
  410. item.Unit = v.Unit
  411. item.Frequency = v.Frequency
  412. if v.Frequency != "半年" {
  413. item.Frequency += "度"
  414. }
  415. item.Interface = "SMM"
  416. item.ModifyTime = time.Now()
  417. item.DataState = v.DataState
  418. item.ReleaseTime = v.UpdateRule.ReleaseTime
  419. for i, typeItem := range typeList {
  420. if i == 0 {
  421. item.Type1 = typeItem
  422. } else if i == 1{
  423. item.Type2 = typeItem
  424. } else if i == 2 {
  425. item.Type3 = typeItem
  426. }
  427. }
  428. indexList = append(indexList, item)
  429. }
  430. return
  431. }