currency_rate.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package fms
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. jsoniter "github.com/json-iterator/go"
  7. "hongze/fms_api/global"
  8. "hongze/fms_api/models/fms"
  9. "hongze/fms_api/services/alarm_msg"
  10. "hongze/fms_api/utils"
  11. "strconv"
  12. "time"
  13. )
  14. const (
  15. CurrencyRateApiHost = "https://jisuhuilv.market.alicloudapi.com"
  16. CurrencyRateExchangeSingle = "/exchange/single"
  17. CurrencyRateApiAppCode = "22553c4ba74545568aba70ac6cfd441d"
  18. CurrencyRateApiAppKey = "203889624"
  19. CurrencyRateApiAppSecret = "voampGGl0yGNx5xA1sZdmZlV2EiBct2P"
  20. )
  21. type CurrencyRateApiResp struct {
  22. Status int `json:"status"`
  23. Msg string `json:"msg"`
  24. Result struct {
  25. Currency string `json:"currency"`
  26. Name string `json:"name"`
  27. List map[string]struct {
  28. Name string `json:"name"`
  29. Rate string `json:"rate"`
  30. UpdateTime string `json:"updatetime"`
  31. } `json:"list"`
  32. } `json:"result"`
  33. }
  34. type CurrencyRateItem struct {
  35. Name string `json:"name"`
  36. Code string `json:"code"`
  37. Rate float64 `json:"rate"`
  38. UpdateTime time.Time `json:"update_time"`
  39. }
  40. // CurlCurrencyRateApi 请求货币汇率接口
  41. func CurlCurrencyRateApi() (resList []*CurrencyRateItem, err error) {
  42. defer func() {
  43. if err != nil {
  44. go alarm_msg.SendAlarmMsg("请求汇率接口失败, Err: "+err.Error(), 3)
  45. }
  46. }()
  47. // 请求汇率接口
  48. query := "?currency=CNY"
  49. reqUrl := fmt.Sprint(CurrencyRateApiHost, CurrencyRateExchangeSingle, query)
  50. auth := fmt.Sprintf("APPCODE %s", CurrencyRateApiAppCode)
  51. resultByte, e := utils.PublicGetRequest(reqUrl, auth)
  52. if e != nil {
  53. err = fmt.Errorf("HttpCurrencyRateApi errMsg: %s", e.Error())
  54. return
  55. }
  56. if len(resultByte) == 0 {
  57. err = fmt.Errorf("HttpCurrencyRateApi empty data")
  58. return
  59. }
  60. // 汇率结果
  61. results := new(CurrencyRateApiResp)
  62. if e := json.Unmarshal(resultByte, &results); e != nil {
  63. err = fmt.Errorf("rate api result unmarshal err: %s", e.Error())
  64. return
  65. }
  66. if results.Status != 0 {
  67. err = fmt.Errorf("curl rate api errMsg: %s", results.Msg)
  68. return
  69. }
  70. list := results.Result.List
  71. if list == nil {
  72. err = fmt.Errorf("rate api list is empty")
  73. return
  74. }
  75. resList = make([]*CurrencyRateItem, 0)
  76. for k, v := range list {
  77. item := new(CurrencyRateItem)
  78. item.Code = k
  79. item.Name = v.Name
  80. f, e := strconv.ParseFloat(v.Rate, 64)
  81. if e != nil {
  82. err = fmt.Errorf("rate api rate parse err: %v", e)
  83. return
  84. }
  85. item.Rate = f
  86. t, e := time.ParseInLocation(utils.FormatDateTime, v.UpdateTime, time.Local)
  87. if e != nil {
  88. global.LOG.Errorf("rate api time parse err:", e)
  89. continue
  90. }
  91. item.UpdateTime = t
  92. resList = append(resList, item)
  93. }
  94. return
  95. }
  96. // GetTodayCurrencyRateList 获取今日货币及汇率列表
  97. func GetTodayCurrencyRateList() (list []*fms.CurrencyUnitItem, err error) {
  98. list = make([]*fms.CurrencyUnitItem, 0)
  99. // 货币列表
  100. ob := new(fms.CurrencyUnit)
  101. cond := `enable = 1`
  102. pars := make([]interface{}, 0)
  103. currencyList, e := ob.List(cond, pars)
  104. if e != nil {
  105. err = fmt.Errorf("获取货币列表失败, Err: %s", e.Error())
  106. return
  107. }
  108. rateMap := make(map[string]float64)
  109. rateList := make([]*CurrencyRateItem, 0)
  110. // 读取缓存
  111. cacheJson, _ := global.Redis.Get(context.TODO(), utils.CACHE_KEY_CURRENCY_RMB_RATE).Result()
  112. if cacheJson != "" {
  113. if e = jsoniter.UnmarshalFromString(cacheJson, &rateList); e != nil {
  114. err = fmt.Errorf("解析汇率缓存数据失败, Err: %s", e.Error())
  115. return
  116. }
  117. }
  118. // 请求汇率接口
  119. if cacheJson == "" {
  120. rateList, e = CurlCurrencyRateApi()
  121. if e != nil {
  122. err = fmt.Errorf("请求汇率接口失败, Err: %s", e.Error())
  123. return
  124. }
  125. if len(rateList) == 0 {
  126. err = fmt.Errorf("汇率接口返回数据为空")
  127. return
  128. }
  129. newCache, e := jsoniter.MarshalToString(rateList)
  130. if e != nil {
  131. err = fmt.Errorf("写入汇率缓存失败, Err: %s", e.Error())
  132. return
  133. }
  134. now := time.Now()
  135. todayLast := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, time.Local)
  136. sub := todayLast.Sub(now)
  137. _ = global.Redis.SetEX(context.TODO(), utils.CACHE_KEY_CURRENCY_RMB_RATE, newCache, sub)
  138. }
  139. for i := range rateList {
  140. rateMap[rateList[i].Code] = rateList[i].Rate
  141. }
  142. for i := range currencyList {
  143. r := rateMap[currencyList[i].Code]
  144. if currencyList[i].Code == fms.BaseCurrencyCode {
  145. r = 1
  146. }
  147. list = append(list, &fms.CurrencyUnitItem{
  148. Name: currencyList[i].Name,
  149. UnitName: currencyList[i].UnitName,
  150. Code: currencyList[i].Code,
  151. Enable: currencyList[i].Enable,
  152. RMBRate: r,
  153. FlagImg: currencyList[i].FlagImg,
  154. })
  155. }
  156. return
  157. }