|
@@ -1,14 +1,61 @@
|
|
|
package web_hook
|
|
|
|
|
|
import (
|
|
|
+ "eta/eta_mini_ht_api/common/component/cache"
|
|
|
logger "eta/eta_mini_ht_api/common/component/log"
|
|
|
"eta/eta_mini_ht_api/common/exception"
|
|
|
"eta/eta_mini_ht_api/controllers"
|
|
|
userService "eta/eta_mini_ht_api/domian/user"
|
|
|
+ accountService "eta/eta_mini_ht_api/service/user"
|
|
|
"fmt"
|
|
|
+ "golang.org/x/time/rate"
|
|
|
+ "net/http"
|
|
|
+ "strings"
|
|
|
+ "sync"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
+var (
|
|
|
+ // 初始化限流器
|
|
|
+ accountRateLimiter = NewThirdRateLimiter(rate.Every(1*time.Second), 1)
|
|
|
+ rdServer = cache.GetInstance()
|
|
|
+)
|
|
|
+
|
|
|
+type ThirdRateLimiter struct {
|
|
|
+ limiters sync.Map // 存储每个用户的限流器
|
|
|
+ defaultLimiter *rate.Limiter // 默认限流器
|
|
|
+}
|
|
|
+
|
|
|
+func NewThirdRateLimiter(limit rate.Limit, burst int) *ThirdRateLimiter {
|
|
|
+ return &ThirdRateLimiter{
|
|
|
+ defaultLimiter: rate.NewLimiter(limit, burst),
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (url *ThirdRateLimiter) Allow(idNo string) bool {
|
|
|
+ if limiter, ok := url.limiters.Load(idNo); ok {
|
|
|
+ return limiter.(*rate.Limiter).Allow()
|
|
|
+ }
|
|
|
+ // 创建新的限流器并存储
|
|
|
+ newLimiter := rate.NewLimiter(url.defaultLimiter.Limit(), url.defaultLimiter.Burst())
|
|
|
+ url.limiters.Store(idNo, newLimiter)
|
|
|
+ return newLimiter.Allow()
|
|
|
+}
|
|
|
+
|
|
|
+// ThirdRateLimitFilter 回调接口限流
|
|
|
+func ThirdRateLimitFilter(idNo string) (code int) {
|
|
|
+ if idNo == "" {
|
|
|
+ code = http.StatusBadRequest
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if !accountRateLimiter.Allow(idNo) {
|
|
|
+ code = http.StatusTooManyRequests
|
|
|
+ return
|
|
|
+ }
|
|
|
+ code = http.StatusOK
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
type HTFuturesAccountController struct {
|
|
|
controllers.WebHookController
|
|
|
}
|
|
@@ -188,65 +235,78 @@ func (h *HTFuturesAccountController) SyncCustomerRiskLevel() {
|
|
|
// @router /v1/syncAccountInfo/ [post]
|
|
|
func (h *HTFuturesAccountController) SyncCustomerAccountInfo() {
|
|
|
controllers.WrapWebhook(&h.WebHookController, func() (result *controllers.WrapData, err error) {
|
|
|
- result = h.InitWrapData("同步风险等级")
|
|
|
- syncCustomerRiskLevelReq := new(SyncCustomerRiskLevelReq)
|
|
|
+ result = h.InitWrapData("同步开户信息")
|
|
|
+ syncCustomerRiskLevelReq := new(AccountOpenInfoReq)
|
|
|
h.GetPostParams(syncCustomerRiskLevelReq)
|
|
|
- custInfo := syncCustomerRiskLevelReq.CustInfo
|
|
|
- riskInfo := syncCustomerRiskLevelReq.RiskInfo
|
|
|
+ if ThirdRateLimitFilter(syncCustomerRiskLevelReq.IdNo) != 200 {
|
|
|
+ err = exception.New(exception.TooManyRequest)
|
|
|
+ h.FailedResult("接口请求太频繁,请稍后重试", result)
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
- if custInfo.ClientName == "" {
|
|
|
- err = exception.New(exception.SyncRiskError)
|
|
|
+ //if syncCustomerRiskLevelReq.MobileTel != "" && syncCustomerRiskLevelReq.DealMobileTel != syncCustomerRiskLevelReq.MobileTel {
|
|
|
+ // err = exception.New(exception.SyncRiskError)
|
|
|
+ // h.FailedResult(fmt.Sprintf("柜台预留手机号码不一致,测评手机:%s,柜台预留手机:%s", syncCustomerRiskLevelReq.DealMobileTel, syncCustomerRiskLevelReq.MobileTel), result)
|
|
|
+ // return
|
|
|
+ //}
|
|
|
+ if syncCustomerRiskLevelReq.ClientName == "" {
|
|
|
+ err = exception.New(exception.SyncAccountStatusError)
|
|
|
h.FailedResult("用户名字不能为空", result)
|
|
|
return
|
|
|
}
|
|
|
- if custInfo.MobileTel == "" {
|
|
|
- err = exception.New(exception.SyncRiskError)
|
|
|
+ if syncCustomerRiskLevelReq.MobileTel == "" {
|
|
|
+ err = exception.New(exception.SyncAccountStatusError)
|
|
|
h.FailedResult("手机号码不能为空", result)
|
|
|
return
|
|
|
}
|
|
|
- if custInfo.IdNo == "" {
|
|
|
- err = exception.New(exception.SyncRiskError)
|
|
|
- h.FailedResult("身份证号不能为空", result)
|
|
|
+ if _, ok := idKindMap[syncCustomerRiskLevelReq.IdKind]; !ok {
|
|
|
+ err = exception.New(exception.SyncAccountStatusError)
|
|
|
+ validIdKind := make([]string, 0)
|
|
|
+ for _, v := range idKindMap {
|
|
|
+ validIdKind = append(validIdKind, string(v))
|
|
|
+ }
|
|
|
+ h.FailedResult(fmt.Sprintf("证件类型不合法,当前只支持[%s]", strings.Join(validIdKind, ",")), result)
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
- //if !utils.IsValidIDCard(custInfo.IdNo) && !utils.IsValidOldIDCard(custInfo.IdNo) {
|
|
|
- // err = exception.New(exception.SyncRiskError)
|
|
|
- // h.FailedResult("身份证号不合法", result)
|
|
|
- // return
|
|
|
- //}
|
|
|
- if riskInfo.CorpRiskLevel == "" {
|
|
|
- err = exception.New(exception.SyncRiskError)
|
|
|
- h.FailedResult("风险等级不能为空", result)
|
|
|
+ if syncCustomerRiskLevelReq.IdNo == "" {
|
|
|
+ err = exception.New(exception.SyncAccountStatusError)
|
|
|
+ h.FailedResult("证号号码不能为空", result)
|
|
|
return
|
|
|
}
|
|
|
- if riskInfo.CorpEndDate == "" {
|
|
|
- err = exception.New(exception.SyncRiskError)
|
|
|
- h.FailedResult("风险测评有效结束日期不能为空", result)
|
|
|
+ idBeginDate, parseErr := time.Parse(time.DateOnly, syncCustomerRiskLevelReq.IdBeginDate)
|
|
|
+ if parseErr != nil {
|
|
|
+ err = exception.New(exception.SyncAccountStatusError)
|
|
|
+ h.FailedResult("身份证有效开始时间不合法["+syncCustomerRiskLevelReq.IdBeginDate+"]", result)
|
|
|
return
|
|
|
}
|
|
|
- if risk, ok := riskMappingMap[riskInfo.CorpRiskLevel]; ok {
|
|
|
- riskInfo.CorpRiskLevel = risk
|
|
|
- } else {
|
|
|
- err = exception.New(exception.SyncRiskError)
|
|
|
- h.FailedResult(fmt.Sprintf("风险等级不合法,应答结果:%s", riskInfo.CorpRiskLevel), result)
|
|
|
+ idEndDate, parseErr := time.Parse(time.DateOnly, syncCustomerRiskLevelReq.IdEndDate)
|
|
|
+ if parseErr != nil {
|
|
|
+ err = exception.New(exception.SyncAccountStatusError)
|
|
|
+ h.FailedResult("身份证有效结束时间不合法["+syncCustomerRiskLevelReq.IdEndDate+"]", result)
|
|
|
return
|
|
|
}
|
|
|
- fmt.Println(riskInfo.CorpRiskLevel)
|
|
|
- err = userService.UpdateRiskLevelInfo(userService.RiskLevelInfoDTO{
|
|
|
- Name: custInfo.ClientName,
|
|
|
- PhoneNumber: custInfo.MobileTel,
|
|
|
- RiskLevel: riskInfo.CorpRiskLevel,
|
|
|
- RiskValidEndDate: riskInfo.CorpEndDate,
|
|
|
+ if idEndDate.Before(idBeginDate) {
|
|
|
+ err = exception.New(exception.SyncAccountStatusError)
|
|
|
+ h.FailedResult("身份证有效结束时间不合法,开始日期不能大于结束日期", result)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ err = accountService.UpdateUserAccountOpenStatus(accountService.AccountStatusDTO{
|
|
|
+ MobileTel: syncCustomerRiskLevelReq.MobileTel,
|
|
|
+ ClientName: syncCustomerRiskLevelReq.ClientName,
|
|
|
+ IdKind: syncCustomerRiskLevelReq.IdKind,
|
|
|
+ IdNo: syncCustomerRiskLevelReq.IdNo,
|
|
|
+ IdBeginDate: idBeginDate,
|
|
|
+ IdEndDate: idEndDate,
|
|
|
+ AccountStatus: string(syncCustomerRiskLevelReq.AccountStatus),
|
|
|
+ ErrorMessage: syncCustomerRiskLevelReq.ErrorMessage,
|
|
|
})
|
|
|
if err != nil {
|
|
|
logger.ErrorWithTraceId(h.Ctx, err.Error())
|
|
|
h.FailedResult(err.Error(), result)
|
|
|
- err = exception.New(exception.SyncRiskError)
|
|
|
+ err = exception.New(exception.SyncAccountStatusError)
|
|
|
return
|
|
|
}
|
|
|
- logger.InfoWithTraceId(h.Ctx, err.Error())
|
|
|
- result = h.InitWrapData("同步风险等级成功")
|
|
|
+ result = h.InitWrapData("同步开户信息成功")
|
|
|
h.SuccessResult("success", syncCustomerRiskLevelReq, result)
|
|
|
return
|
|
|
})
|
|
@@ -276,3 +336,35 @@ type SyncCustomerAccountInfoReq struct {
|
|
|
CustInfo CustInfo `json:"custInfo"`
|
|
|
RiskInfo RiskInfo `json:"riskInfo"`
|
|
|
}
|
|
|
+type AccountStatus string
|
|
|
+type IdKind string
|
|
|
+
|
|
|
+var (
|
|
|
+ accountStatusMap = map[string]AccountStatus{
|
|
|
+ "success": AccountStatusOpenSuccess,
|
|
|
+ "failed": AccountStatusOpenFailed,
|
|
|
+ }
|
|
|
+ idKindMap = map[int]IdKind{
|
|
|
+ 1: Id,
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
+ AccountStatusOpenSuccess AccountStatus = "success"
|
|
|
+ AccountStatusOpenFailed AccountStatus = "failed"
|
|
|
+ Id IdKind = "身份证"
|
|
|
+)
|
|
|
+
|
|
|
+type AccountOpenInfoReq struct {
|
|
|
+ MobileTel string `json:"mobile_tel"`
|
|
|
+ //DealMobileTel string `json:"deal_mobile_tel"`
|
|
|
+ ClientName string `json:"client_name"`
|
|
|
+ IdKind int `json:"id_kind"`
|
|
|
+ IdNo string `json:"id_no"`
|
|
|
+ AccountStatus AccountStatus `json:"account_status"`
|
|
|
+ //ErrorCode int `json:"error_code"`
|
|
|
+ IdBeginDate string `json:"id_begin_date"`
|
|
|
+ IdEndDate string `json:"id_end_date"`
|
|
|
+ ErrorMessage string `json:"error_message"`
|
|
|
+ Timestamp int64 `json:"timestamp"`
|
|
|
+}
|