ht_account_api.go 7.9 KB

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