|
@@ -0,0 +1,310 @@
|
|
|
+package services
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "encoding/json"
|
|
|
+ "errors"
|
|
|
+ "eta/eta_index_lib/models"
|
|
|
+ "eta/eta_index_lib/services/alarm_msg"
|
|
|
+ "eta/eta_index_lib/utils"
|
|
|
+ "fmt"
|
|
|
+ "io"
|
|
|
+ "io/ioutil"
|
|
|
+ "mime/multipart"
|
|
|
+ netHttp "net/http"
|
|
|
+ "strings"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+// getEdbDataFromSmmHttp 通过url获取同花顺的普通数据
|
|
|
+func getEdbDataFromSmmHttp(edbCode, token string) (smmBaseDataAll []*models.BaseFromSmmData, err error) {
|
|
|
+ thsUrl := `https://datapro-api.smm.cn/dapi/quota/data_origin`
|
|
|
+
|
|
|
+ //发送创建请求
|
|
|
+ dataMap := map[string]io.Reader{
|
|
|
+ "token": strings.NewReader("18815284804"),,
|
|
|
+ "request_source": strings.NewReader("18815284804"),
|
|
|
+ "quota_ids": strings.NewReader("18815284804"),
|
|
|
+ "start_date": strings.NewReader("18815284804"),
|
|
|
+ "end_date": strings.NewReader("18815284804"),
|
|
|
+ }
|
|
|
+
|
|
|
+ body, err, _ := smmPostCurl(thsUrl, dataMap, 0, token)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ tmpItems := new(SmmResponse)
|
|
|
+ err = json.Unmarshal(body, &tmpItems)
|
|
|
+ if err != nil {
|
|
|
+ err = errors.New("GetEdbDataFromSmm json.Unmarshal Err:" + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if tmpItems.Code != 0 {
|
|
|
+ err = errors.New(tmpItems.Msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, quota := range tmpItems.Quota {
|
|
|
+ for _, v := range quota.Data {
|
|
|
+ createTime, err := time.Parse(v.Create, utils.FormatDateTime)
|
|
|
+ if err != nil {
|
|
|
+ err = errors.New("GetEdbDataFromSmm time.Parse Err:" + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ item := &models.BaseFromSmmData{
|
|
|
+ IndexCode: quota.QuotaID,
|
|
|
+ DataTime: v.Date,
|
|
|
+ Value: v.Value,
|
|
|
+ CreateTime: createTime,
|
|
|
+ ModifyTime: createTime,
|
|
|
+ DataTimestamp: createTime.UnixNano() / 1e6,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// Data is a struct that represents the data field in the JSON string
|
|
|
+type Data struct {
|
|
|
+ Date string `json:"date"`
|
|
|
+ Value string `json:"value"`
|
|
|
+ Create string `json:"create"`
|
|
|
+}
|
|
|
+
|
|
|
+// Quota is a struct that represents the quota information in the JSON string
|
|
|
+type Quota struct {
|
|
|
+ QuotaID string `json:"quota_id"`
|
|
|
+ QuotaName string `json:"quota_name"`
|
|
|
+ Unit string `json:"unit"`
|
|
|
+ Frequency string `json:"frequency"`
|
|
|
+ ValueType string `json:"value_type"`
|
|
|
+ Precision int `json:"precision"`
|
|
|
+ PermState int `json:"perm_state"`
|
|
|
+ Data []Data `json:"data"`
|
|
|
+}
|
|
|
+
|
|
|
+// Response is a struct that represents the whole JSON string
|
|
|
+type SmmResponse struct {
|
|
|
+ Code int `json:"code"`
|
|
|
+ Msg string `json:"msg"`
|
|
|
+ Quota []Quota `json:"data"`
|
|
|
+}
|
|
|
+
|
|
|
+// smmPostCurl post请求同花顺接口
|
|
|
+func smmPostCurl(urlStr string, dataMap map[string]io.Reader, num int, token string) (body []byte, err error, errMsg string) {
|
|
|
+ logMsg := ``
|
|
|
+ defer func() {
|
|
|
+ if err != nil {
|
|
|
+ if logMsg != `` {
|
|
|
+ errMsg = logMsg
|
|
|
+ go alarm_msg.SendAlarmMsg("post请求SMM接口失败,ERR:"+err.Error()+";errMsg:"+errMsg, 3)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ // 创建一个新的buffer,用于存储请求体
|
|
|
+ var reqBody bytes.Buffer
|
|
|
+ writer := multipart.NewWriter(&reqBody)
|
|
|
+
|
|
|
+ // 添加Form-data参数
|
|
|
+ for key, value := range dataMap {
|
|
|
+ part, err := writer.CreateFormFile(key, key)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error creating form file:", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ _, err = io.Copy(part, value)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error copying file content:", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 关闭multipart writer
|
|
|
+ writer.Close()
|
|
|
+
|
|
|
+ // 发送POST请求
|
|
|
+ req, err := netHttp.NewRequest("POST", urlStr, &reqBody)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error creating request:", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ req.Header.Set("Content-Type", writer.FormDataContentType())
|
|
|
+
|
|
|
+ client := &netHttp.Client{}
|
|
|
+ resp, err := client.Do(req)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error sending request:", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ defer resp.Body.Close()
|
|
|
+
|
|
|
+ // 处理响应
|
|
|
+ fmt.Println("Response Status:", resp.Status)
|
|
|
+
|
|
|
+ body, err = ioutil.ReadAll(resp.Body)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error reading response body:", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ utils.FileLog.Info("SMM刷新token:" + string(body))
|
|
|
+
|
|
|
+ var response SmmResponse
|
|
|
+ err = json.Unmarshal(body, &response)
|
|
|
+ if err != nil {
|
|
|
+ utils.FileLog.Info("post Err:", err.Error(), ";url:", urlStr, ";response:", string(body))
|
|
|
+ err = errors.New("Unmarshal Err:" + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ utils.FileLog.Info(fmt.Sprint("post request url:", urlStr, ";token:", token, ";response:", string(body)))
|
|
|
+ logMsg = fmt.Sprint("post request url:", urlStr, ";token:", token, ";response:", string(body))
|
|
|
+
|
|
|
+ //如果是token失效,同时只是第一次请求(没有尝试强制刷新token,那么重新请求)
|
|
|
+ if utils.InArrayByInt([]int{-10020001, -10020002}, int(response.Code)) && num <= 0 {
|
|
|
+ //token失效
|
|
|
+ token, err = refreshSmmAccessToken()
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ num++
|
|
|
+ return smmPostCurl(urlStr, dataMap, num, token)
|
|
|
+ } else if response.Code != 0 {
|
|
|
+ utils.FileLog.Info(fmt.Sprint("post data err:", response.Msg, ";url:", urlStr, ";response:", string(body)))
|
|
|
+ err = errors.New(response.Msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetSmmAccessToken 获取accessToken
|
|
|
+func GetSmmAccessToken(isRefresh bool) (token string, err error) {
|
|
|
+ defer func() {
|
|
|
+ if err != nil {
|
|
|
+ go alarm_msg.SendAlarmMsg("获取SMM的token失败,ERR:"+err.Error(), 3)
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ redisKey := utils.CACHE_EDB_SMM_SERVER_TOKEN
|
|
|
+ token, redisErr := utils.Rc.RedisString(redisKey)
|
|
|
+ //如果从redis中accessToken 获取失败或者token为空了,再或者需要强制刷新了,那么重新获取accessToken
|
|
|
+ if redisErr != nil || token == `` || isRefresh {
|
|
|
+ token, _ = refreshSmmAccessToken()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// refreshSmmAccessToken 强制刷新获取accessToken
|
|
|
+func refreshSmmAccessToken() (token string, err error) {
|
|
|
+ defer func() {
|
|
|
+ if err != nil {
|
|
|
+ go alarm_msg.SendAlarmMsg("刷新SMM的token失败;ERR:"+err.Error(), 3)
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ tokenInfo, tmpErr := getSmmAccessToken()
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ token = tokenInfo.Token
|
|
|
+
|
|
|
+ //token存入redis
|
|
|
+ redisKey := utils.CACHE_EDB_SMM_SERVER_TOKEN
|
|
|
+ err = utils.Rc.Put(redisKey, token, time.Hour*24*7)
|
|
|
+ if err != nil {
|
|
|
+ err = fmt.Errorf("获取SMM的token成功;SMM token存入redis失败,ERR:%s", err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+type GetSmmTokenResp struct {
|
|
|
+ Code int `json:"code"`
|
|
|
+ Msg string `json:"msg"`
|
|
|
+ Data SmmTokenData `json:"data"`
|
|
|
+}
|
|
|
+
|
|
|
+type SmmTokenData struct {
|
|
|
+ Token string `json:"token"`
|
|
|
+}
|
|
|
+
|
|
|
+// getSmmAccessToken token内部请求接口
|
|
|
+func getSmmAccessToken() (tokenData SmmTokenData, err error) {
|
|
|
+ defer func() {
|
|
|
+ if err != nil {
|
|
|
+ go alarm_msg.SendAlarmMsg("更新SMM的token失败;ERR:"+err.Error(), 3)
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ url := "https://datapro-api.smm.cn/dapi/user/auth"
|
|
|
+
|
|
|
+ // 准备Form-data参数
|
|
|
+ values := map[string]io.Reader{
|
|
|
+ "user_name": strings.NewReader("18815284804"),
|
|
|
+ "password": strings.NewReader(utils.MD5("huangcf@cbnb.com.cn")),
|
|
|
+ "source": strings.NewReader("datapro"),
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建一个新的buffer,用于存储请求体
|
|
|
+ var body bytes.Buffer
|
|
|
+ writer := multipart.NewWriter(&body)
|
|
|
+
|
|
|
+ // 添加Form-data参数
|
|
|
+ for key, value := range values {
|
|
|
+ part, err := writer.CreateFormFile(key, key)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error creating form file:", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ _, err = io.Copy(part, value)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error copying file content:", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 关闭multipart writer
|
|
|
+ writer.Close()
|
|
|
+
|
|
|
+ // 发送POST请求
|
|
|
+ req, err := netHttp.NewRequest("POST", url, &body)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error creating request:", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ req.Header.Set("Content-Type", writer.FormDataContentType())
|
|
|
+
|
|
|
+ client := &netHttp.Client{}
|
|
|
+ resp, err := client.Do(req)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error sending request:", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ defer resp.Body.Close()
|
|
|
+
|
|
|
+ // 处理响应
|
|
|
+ fmt.Println("Response Status:", resp.Status)
|
|
|
+
|
|
|
+ bodyContent, err := ioutil.ReadAll(resp.Body)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error reading response body:", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ utils.FileLog.Info("SMM刷新token:" + string(bodyContent))
|
|
|
+
|
|
|
+ var tokenResp GetSmmTokenResp
|
|
|
+ err = json.Unmarshal(bodyContent, &tokenResp)
|
|
|
+ if err != nil {
|
|
|
+ err = errors.New("Unmarshal Err:" + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if tokenResp.Code != 0 {
|
|
|
+ err = errors.New("getAccessToken err:" + tokenResp.Msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ tokenData = tokenResp.Data
|
|
|
+
|
|
|
+ return
|
|
|
+}
|