ht_api.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. package api
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "eta/eta_mini_ht_api/common/component/cache"
  6. "eta/eta_mini_ht_api/common/component/config"
  7. logger "eta/eta_mini_ht_api/common/component/log"
  8. "eta/eta_mini_ht_api/common/contants"
  9. "eta/eta_mini_ht_api/common/exception"
  10. "eta/eta_mini_ht_api/common/utils/auth"
  11. "eta/eta_mini_ht_api/common/utils/client"
  12. "eta/eta_mini_ht_api/common/utils/redis"
  13. "fmt"
  14. "io"
  15. "sync"
  16. "time"
  17. )
  18. const (
  19. clientSuitInfoUrl = "/wt/front/api/open/api/getClientSuitInfo"
  20. accessTokenUrl = "/api/openapi/authless/token"
  21. )
  22. var (
  23. htFacadeOnce sync.Once
  24. htFacade *HTApi
  25. )
  26. type HTApi struct {
  27. htConfig *config.HTBizConfig
  28. // HTTP请求客户端
  29. client *client.HttpClient
  30. redisUtils *cache.RedisCache
  31. }
  32. func GetInstance() *HTApi {
  33. htFacadeOnce.Do(func() {
  34. htFacade = &HTApi{
  35. htConfig: config.GetConfig(contants.HT).(*config.HTBizConfig),
  36. client: client.DefaultClient(),
  37. redisUtils: cache.GetInstance()}
  38. })
  39. return htFacade
  40. }
  41. type ClientSuitInfoReq struct {
  42. ClientName string `json:"client_name"`
  43. IdKind int `json:"id_kind"`
  44. IdNo string `json:"id_no"`
  45. }
  46. type CustomerRiskReq struct {
  47. MobileTel string `json:"mobile_tel"`
  48. ClientName string `json:"client_name"`
  49. IdKind int `json:"id_kind"`
  50. IdNo string `json:"id_no"`
  51. CreateTime string `json:"create_time"`
  52. LoginType string `json:"login_type"`
  53. UserType int `json:"user_type" description:"0:非正式客户;1:正式客户"`
  54. }
  55. func (f *HTApi) EnCodeData(req CustomerRiskReq) (token string, err error) {
  56. publicKey, err := auth.ParsePublicKey(f.htConfig.GetWebhookPublicKey())
  57. if err != nil {
  58. logger.Error("解析公钥失败:%v", err)
  59. err = exception.New(exception.SysError)
  60. return
  61. }
  62. str, err := json.Marshal(req)
  63. if err != nil {
  64. logger.Error("json序列化失败:%v", err)
  65. err = exception.New(exception.SysError)
  66. return
  67. }
  68. rsa, err := auth.EncryptWithRSA(publicKey, str)
  69. if err != nil {
  70. logger.Error("公钥加密失败:%v", err)
  71. err = exception.New(exception.SysError)
  72. return
  73. }
  74. token = base64.StdEncoding.EncodeToString(rsa)
  75. return
  76. }
  77. type EncodeReq struct {
  78. Param string `json:"param"`
  79. }
  80. func (f *HTApi) getToken() (token string, err error) {
  81. accessToken := redis.GenerateCAPAccessTokenKey()
  82. token = f.redisUtils.GetString(accessToken)
  83. var tokenInfo TokenInfo
  84. if token == "" {
  85. tokenInfo, err = f.GetAccessToken()
  86. if err != nil {
  87. logger.Error("获取token失败%v", err)
  88. return
  89. }
  90. var parseErr error
  91. expireTime, parseErr := time.Parse(time.DateTime, tokenInfo.ExpiresAt)
  92. if parseErr != nil {
  93. logger.Error("解析过期时间失败:%v", parseErr)
  94. err = parseErr
  95. return
  96. }
  97. duration := expireTime.Sub(time.Now()).Seconds()
  98. token = tokenInfo.AccessToken
  99. _ = f.redisUtils.SetString(accessToken, tokenInfo.AccessToken, int(duration)-5)
  100. }
  101. return
  102. }
  103. func (f *HTApi) GetCustomerRiskLevelInfo(req ClientSuitInfoReq) (info CustomerAccountInfo, err error) {
  104. url := f.htConfig.GetAccountApiUrl() + clientSuitInfoUrl
  105. token, err := f.getToken()
  106. if err != nil {
  107. return
  108. }
  109. publicKey, err := auth.ParsePublicKey(f.htConfig.GetWebhookPublicKey())
  110. if err != nil {
  111. logger.Error("解析公钥失败:%v", err)
  112. }
  113. reqStr, err := json.Marshal(req)
  114. encodeData, _ := auth.EncryptWithRSA(publicKey, reqStr)
  115. resp, err := f.client.PostWithAuth(url, EncodeReq{
  116. Param: base64.StdEncoding.EncodeToString(encodeData),
  117. }, token)
  118. if err != nil {
  119. logger.Error("调用CAP customerRiskInfo接口失败:[%v]", err)
  120. return
  121. }
  122. defer func(Body io.ReadCloser) {
  123. closeErr := Body.Close()
  124. if closeErr != nil {
  125. logger.Error("关闭Response失败:%v", closeErr)
  126. }
  127. }(resp.Body)
  128. body, _ := io.ReadAll(resp.Body)
  129. return decodeResponse(body)
  130. }
  131. type AccessTokenReq struct {
  132. AppId string `json:"app_id"`
  133. SecretKey string `json:"secret_key"`
  134. }
  135. func (f *HTApi) GetAccessToken() (token TokenInfo, err error) {
  136. url := f.htConfig.GetAccountApiUrl() + accessTokenUrl
  137. req := AccessTokenReq{
  138. AppId: f.htConfig.GetAppId(),
  139. SecretKey: f.htConfig.GetSecretKey(),
  140. }
  141. resp, err := f.client.Post(url, req)
  142. if err != nil {
  143. logger.Error("调用CAP accessToken接口失败:[%v]", err)
  144. return
  145. }
  146. defer func(Body io.ReadCloser) {
  147. closeErr := Body.Close()
  148. if closeErr != nil {
  149. logger.Error("关闭Response失败:%v", closeErr)
  150. }
  151. }(resp.Body)
  152. body, _ := io.ReadAll(resp.Body)
  153. var tokenResp AccessTokenResp
  154. err = json.Unmarshal(body, &tokenResp)
  155. if err != nil {
  156. logger.Warn("[cap 接口调用]解析cap token接口应答失败:%v", err)
  157. err = exception.New(exception.GetCapTokenFailed)
  158. return
  159. }
  160. if tokenResp.Error.ErrorNo != "0" {
  161. logger.Warn("[cap 接口调用] 获取token失败:[code:%v, msg:%v, path:%v]", tokenResp.Error.ErrorNo, tokenResp.Error.ErrorInfo, tokenResp.Error.ErrorPathInfo)
  162. err = exception.NewWithException(exception.GetCapTokenFailed, tokenResp.Error.ErrorInfo)
  163. return
  164. }
  165. token = TokenInfo{
  166. AccessToken: tokenResp.Data.AccessToken,
  167. ExpiresAt: tokenResp.Data.ExpiresAt,
  168. }
  169. return
  170. }
  171. type AccessTokenResp struct {
  172. Error Error `json:"error"`
  173. Data AccessTokenData `json:"data"`
  174. }
  175. type Error struct {
  176. ErrorNo string `json:"error_no"`
  177. ErrorInfo string `json:"error_info"`
  178. ErrorPathInfo string `json:"error_path_info"`
  179. }
  180. type AccessTokenData struct {
  181. AccessToken string `json:"accessToken"`
  182. ExpiresAt string `json:"expiresAt"`
  183. }
  184. type TokenInfo struct {
  185. AccessToken string
  186. ExpiresAt string
  187. }
  188. type CustomerRiskInfoResp struct {
  189. Error Error `json:"error"`
  190. Data string `json:"data"`
  191. }
  192. type SyncCustomerRiskLevelReq struct {
  193. CustInfo CustInfo `json:"custInfo"`
  194. RiskInfo RiskInfo `json:"riskInfo"`
  195. }
  196. type CustInfo struct {
  197. MobileTel string `json:"mobile_tel"`
  198. ClientName string `json:"client_name"`
  199. IdKind string `json:"id_kind"`
  200. IdNo string `json:"id_no"`
  201. IdBeginDate string `json:"id_begindate"`
  202. IdEndDate string `json:"id_enddate"`
  203. }
  204. type RiskInfo struct {
  205. CorpBeginDate string `json:"corp_begin_date"`
  206. CorpEndDate string `json:"corp_end_date"`
  207. UserInvestTerm string `json:"user_invest_term"`
  208. UserInvestKind string `json:"user_invest_kind"`
  209. CorpRiskLevel string `json:"corp_risk_level"`
  210. }
  211. type CustomerAccountInfo struct {
  212. CustInfo CustInfo `json:"custInfo"`
  213. RiskInfo RiskInfo `json:"riskInfo"`
  214. }
  215. func decodeResponse(resp []byte) (info CustomerAccountInfo, err error) {
  216. customerRiskInfoResp := new(CustomerRiskInfoResp)
  217. err = json.Unmarshal(resp, &customerRiskInfoResp)
  218. if err != nil {
  219. logger.Error("customerRiskInfoResp解析失败: %v", err)
  220. return
  221. }
  222. if err != nil {
  223. logger.Warn("[cap 接口调用]解析客户风险信息接口应答失败:%v", err)
  224. err = exception.New(exception.GetCapTokenFailed)
  225. return
  226. }
  227. if customerRiskInfoResp.Error.ErrorNo != "0" {
  228. logger.Warn("[cap 接口调用] 获取客户风险信息失败:[code:%v, msg:%v, path:%v]", customerRiskInfoResp.Error.ErrorNo, customerRiskInfoResp.Error.ErrorInfo, customerRiskInfoResp.Error.ErrorPathInfo)
  229. err = exception.NewWithException(exception.GetCustomerRiskInfoFailed, customerRiskInfoResp.Error.ErrorInfo)
  230. return
  231. }
  232. privateKey, err := auth.ParsePrivateKey(htFacade.htConfig.GetWebhookPrivateKey())
  233. if err != nil {
  234. logger.Error("解析私钥失败: %v", err)
  235. return
  236. }
  237. decodeData, err := auth.DecryptWithRSA(privateKey, customerRiskInfoResp.Data)
  238. if err != nil {
  239. logger.Error("解密请求体失败: %v", err)
  240. return
  241. }
  242. fmt.Printf("解密后的请求: %v", string(decodeData))
  243. err = json.Unmarshal(decodeData, &info)
  244. if err != nil {
  245. logger.Error("customerInfo解析失败: %v", err)
  246. return
  247. }
  248. return
  249. }