Browse Source

对接一部分

zwxi 1 year ago
parent
commit
2599e7d18b

+ 7 - 1
controllers/base_from_smm.go

@@ -44,7 +44,13 @@ func (this *SmmController) Add() {
 	cacheKey = utils.CACHE_EDB_DATA_ADD + strconv.Itoa(source) + "_" + req.EdbCode
 	if !utils.Rc.IsExist(cacheKey) {
 		utils.Rc.SetNX(cacheKey, 1, 1*time.Minute)
-		err = models.AddEdbDataFromSmm(req.EdbCode)
+		smmBaseDataAll, err := services.GetEdbDataFromSmm(req.EdbCode)
+		if err!= nil {
+			br.Msg = "获取指标信息失败!"
+			br.ErrMsg = "获取指标信息失败 GetEdbDataFromSmm,Err:" + err.Error()
+			return
+		}
+		err = models.AddEdbDataFromSmm(req.EdbCode, smmBaseDataAll)
 		if err != nil {
 			br.Msg = "获取指标信息失败!"
 			br.ErrMsg = "获取指标信息失败 AddEdbDataFromSmm,Err:" + err.Error()

+ 1 - 12
models/base_from_smm.go

@@ -38,19 +38,8 @@ func GetBaseFromSmmDataByCondition(condition string, pars []interface{}) (list [
 }
 
 // 新增有色指标数据
-func AddEdbDataFromSmm(edbCode string) (err error) {
+func AddEdbDataFromSmm(edbCode string, smmBaseDataAll []*BaseFromSmmData) (err error) {
 	o := orm.NewOrm()
-
-	var condition string
-	var pars []interface{}
-	if edbCode != "" {
-		condition += " AND index_code=? "
-		pars = append(pars, edbCode)
-	}
-	smmBaseDataAll, err := GetBaseFromSmmDataByCondition(condition, pars)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		return
-	}
 	var isAdd bool
 	addSql := ` INSERT INTO edb_data_ys(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
 	existMap := make(map[string]string)

+ 28 - 0
services/base_from_smm.go

@@ -218,3 +218,31 @@ func SmmIndexHandle(baseFilePath, renameFilePath, indexName, indexCode, unit, fr
 	}
 	return
 }
+
+func GetEdbDataFromSmm(edbCode string) (smmBaseDataAll []*models.BaseFromSmmData, err error) {
+	// 如果没有配置,获取配置的方式是api,那么就走官方接口
+	if utils.ThsDataMethod == "" || utils.ThsDataMethod == "api" {
+		var token string
+		token, err = GetSmmAccessToken(false)
+		if err != nil {
+			return
+		}
+		return getEdbDataFromSmmHttp(edbCode, token)
+	}
+
+	return getEdbDataFromSmmData(edbCode)
+}
+
+func getEdbDataFromSmmData(edbCode string) (smmBaseDataAll []*models.BaseFromSmmData, err error) {
+	var condition string
+	var pars []interface{}
+	if edbCode != "" {
+		condition += " AND index_code=? "
+		pars = append(pars, edbCode)
+	}
+	smmBaseDataAll, err = models.GetBaseFromSmmDataByCondition(condition, pars)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		return
+	}
+	return
+}

+ 310 - 0
services/base_from_smm_http.go

@@ -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
+}

+ 1 - 0
utils/constants.go

@@ -205,6 +205,7 @@ const (
 	CACHE_EDB_TERMINAL_CODE_URL      = "edb:terminal_code:edb_code:"      // 指标与终端关系的缓存
 	CACHE_EDB_TERMINAL_CODE_GOOD_URL = "edb:terminal_code:good:edb_code:" // 指标与终端关系的缓存, 商品期货
 	CACHE_EDB_THS_SERVER_TOKEN       = "edb:ths_server_token:"            //同花顺调用凭证
+	CACHE_EDB_SMM_SERVER_TOKEN       = "edb:smm_server_token"            //smm调用凭证
 )
 
 // 图表类型