package api import ( "encoding/base64" "encoding/json" "eta/eta_mini_ht_api/common/component/cache" "eta/eta_mini_ht_api/common/component/config" logger "eta/eta_mini_ht_api/common/component/log" "eta/eta_mini_ht_api/common/contants" "eta/eta_mini_ht_api/common/exception" "eta/eta_mini_ht_api/common/utils/auth" "eta/eta_mini_ht_api/common/utils/client" "eta/eta_mini_ht_api/common/utils/redis" "fmt" "io" "sync" "time" ) const ( clientSuitInfoUrl = "/wt/front/api/open/api/getClientSuitInfo" accessTokenUrl = "/api/openapi/authless/token" ) var ( htFacadeOnce sync.Once htFacade *HTApi ) type HTApi struct { htConfig *config.HTBizConfig // HTTP请求客户端 client *client.HttpClient redisUtils *cache.RedisCache } func GetInstance() *HTApi { htFacadeOnce.Do(func() { htFacade = &HTApi{ htConfig: config.GetConfig(contants.HT).(*config.HTBizConfig), client: client.DefaultClient(), redisUtils: cache.GetInstance()} }) return htFacade } type ClientSuitInfoReq struct { ClientName string `json:"client_name"` IdKind int `json:"id_kind"` IdNo string `json:"id_no"` } type CustomerRiskReq struct { MobileTel string `json:"mobile_tel"` ClientName string `json:"client_name"` IdKind int `json:"id_kind"` IdNo string `json:"id_no"` CreateTime string `json:"create_time"` LoginType string `json:"login_type"` } func (f *HTApi) EnCodeData(req CustomerRiskReq) (token string, err error) { publicKey, err := auth.ParsePublicKey(f.htConfig.GetWebhookPublicKey()) if err != nil { logger.Error("解析公钥失败:%v", err) err = exception.New(exception.SysError) return } str, err := json.Marshal(req) if err != nil { logger.Error("json序列化失败:%v", err) err = exception.New(exception.SysError) return } rsa, err := auth.EncryptWithRSA(publicKey, str) if err != nil { logger.Error("公钥加密失败:%v", err) err = exception.New(exception.SysError) return } token = base64.StdEncoding.EncodeToString(rsa) return } type EncodeReq struct { Param string `json:"param"` } func (f *HTApi) getToken() (token string, err error) { accessToken := redis.GenerateCAPAccessTokenKey() token = f.redisUtils.GetString(accessToken) var tokenInfo TokenInfo if token == "" { tokenInfo, err = f.GetAccessToken() if err != nil { logger.Error("获取token失败%v", err) return } var parseErr error expireTime, parseErr := time.Parse(time.DateTime, tokenInfo.ExpiresAt) if parseErr != nil { logger.Error("解析过期时间失败:%v", parseErr) err = parseErr return } duration := expireTime.Sub(time.Now()).Seconds() token = tokenInfo.AccessToken _ = f.redisUtils.SetString(accessToken, tokenInfo.AccessToken, int(duration)-5) } return } func (f *HTApi) GetCustomerRiskLevelInfo(req ClientSuitInfoReq) (info CustomerAccountInfo, err error) { url := f.htConfig.GetAccountApiUrl() + clientSuitInfoUrl token, err := f.getToken() if err != nil { return } publicKey, err := auth.ParsePublicKey(f.htConfig.GetWebhookPublicKey()) if err != nil { logger.Error("解析公钥失败:%v", err) } reqStr, err := json.Marshal(req) encodeData, _ := auth.EncryptWithRSA(publicKey, reqStr) resp, err := f.client.PostWithAuth(url, EncodeReq{ Param: base64.StdEncoding.EncodeToString(encodeData), }, token) if err != nil { logger.Error("调用CAP customerRiskInfo接口失败:[%v]", err) return } defer func(Body io.ReadCloser) { closeErr := Body.Close() if closeErr != nil { logger.Error("关闭Response失败:%v", closeErr) } }(resp.Body) body, _ := io.ReadAll(resp.Body) return decodeResponse(body) } type AccessTokenReq struct { AppId string `json:"app_id"` SecretKey string `json:"secret_key"` } func (f *HTApi) GetAccessToken() (token TokenInfo, err error) { url := f.htConfig.GetAccountApiUrl() + accessTokenUrl req := AccessTokenReq{ AppId: f.htConfig.GetAppId(), SecretKey: f.htConfig.GetSecretKey(), } resp, err := f.client.Post(url, req) if err != nil { logger.Error("调用CAP accessToken接口失败:[%v]", err) return } defer func(Body io.ReadCloser) { closeErr := Body.Close() if closeErr != nil { logger.Error("关闭Response失败:%v", closeErr) } }(resp.Body) body, _ := io.ReadAll(resp.Body) var tokenResp AccessTokenResp err = json.Unmarshal(body, &tokenResp) if err != nil { logger.Warn("[cap 接口调用]解析cap token接口应答失败:%v", err) err = exception.New(exception.GetCapTokenFailed) return } if tokenResp.Error.ErrorNo != "0" { logger.Warn("[cap 接口调用] 获取token失败:[code:%v, msg:%v, path:%v]", tokenResp.Error.ErrorNo, tokenResp.Error.ErrorInfo, tokenResp.Error.ErrorPathInfo) err = exception.NewWithException(exception.GetCapTokenFailed, tokenResp.Error.ErrorInfo) return } token = TokenInfo{ AccessToken: tokenResp.Data.AccessToken, ExpiresAt: tokenResp.Data.ExpiresAt, } return } type AccessTokenResp struct { Error Error `json:"error"` Data AccessTokenData `json:"data"` } type Error struct { ErrorNo string `json:"error_no"` ErrorInfo string `json:"error_info"` ErrorPathInfo string `json:"error_path_info"` } type AccessTokenData struct { AccessToken string `json:"accessToken"` ExpiresAt string `json:"expiresAt"` } type TokenInfo struct { AccessToken string ExpiresAt string } type CustomerRiskInfoResp struct { Error Error `json:"error"` Data string `json:"data"` } type SyncCustomerRiskLevelReq struct { CustInfo CustInfo `json:"custInfo"` RiskInfo RiskInfo `json:"riskInfo"` } type CustInfo struct { MobileTel string `json:"mobile_tel"` ClientName string `json:"client_name"` IdKind string `json:"id_kind"` IdNo string `json:"id_no"` IdBeginDate string `json:"id_begindate"` IdEndDate string `json:"id_enddate"` } type RiskInfo struct { CorpBeginDate string `json:"corp_begin_date"` CorpEndDate string `json:"corp_end_date"` UserInvestTerm string `json:"user_invest_term"` UserInvestKind string `json:"user_invest_kind"` CorpRiskLevel string `json:"corp_risk_level"` } type CustomerAccountInfo struct { CustInfo CustInfo `json:"custInfo"` RiskInfo RiskInfo `json:"riskInfo"` } func decodeResponse(resp []byte) (info CustomerAccountInfo, err error) { customerRiskInfoResp := new(CustomerRiskInfoResp) err = json.Unmarshal(resp, &customerRiskInfoResp) if err != nil { logger.Error("customerRiskInfoResp解析失败: %v", err) return } if err != nil { logger.Warn("[cap 接口调用]解析客户风险信息接口应答失败:%v", err) err = exception.New(exception.GetCapTokenFailed) return } if customerRiskInfoResp.Error.ErrorNo != "0" { logger.Warn("[cap 接口调用] 获取客户风险信息失败:[code:%v, msg:%v, path:%v]", customerRiskInfoResp.Error.ErrorNo, customerRiskInfoResp.Error.ErrorInfo, customerRiskInfoResp.Error.ErrorPathInfo) err = exception.NewWithException(exception.GetCustomerRiskInfoFailed, customerRiskInfoResp.Error.ErrorInfo) return } privateKey, err := auth.ParsePrivateKey(htFacade.htConfig.GetWebhookPrivateKey()) if err != nil { logger.Error("解析私钥失败: %v", err) return } decodeData, err := auth.DecryptWithRSA(privateKey, customerRiskInfoResp.Data) if err != nil { logger.Error("解密请求体失败: %v", err) return } fmt.Printf("解密后的请求: %v", string(decodeData)) err = json.Unmarshal(decodeData, &info) if err != nil { logger.Error("customerInfo解析失败: %v", err) return } return }