diff --git a/app/main/api/internal/logic/agent/applyforagentlogic.go b/app/main/api/internal/logic/agent/applyforagentlogic.go index 697adb4..7c23a9e 100644 --- a/app/main/api/internal/logic/agent/applyforagentlogic.go +++ b/app/main/api/internal/logic/agent/applyforagentlogic.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "strconv" + "strings" "time" "qnc-server/app/main/model" "qnc-server/common/ctxdata" @@ -83,7 +84,24 @@ func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *type } userID, err = l.svcCtx.UserService.RegisterUser(l.ctx, encryptedMobile) if err != nil { - return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "注册用户失败: %v", err) + // 检查是否是并发注册导致的唯一键冲突 + // MySQL错误码: 1062 (23000) - Duplicate entry + errStr := err.Error() + if strings.Contains(errStr, "Duplicate entry") && strings.Contains(errStr, "user_auth.unique_type_key") { + // 并发冲突,重新查询用户 + l.Infof("申请代理, 检测到并发注册冲突,重新查询用户: %s", encryptedMobile) + user, retryErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true}) + if retryErr != nil { + return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "申请代理, 并发冲突后重新查询用户失败: %v", retryErr) + } + if user == nil { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "申请代理, 并发冲突后仍未找到用户") + } + userID = user.Id + l.Infof("申请代理, 并发冲突后获取到已注册用户, userId: %s, mobile: %s", userID, encryptedMobile) + } else { + return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "注册用户失败: %v", err) + } } } else { // 用户已存在 diff --git a/app/main/api/internal/logic/user/mobilecodeloginlogic.go b/app/main/api/internal/logic/user/mobilecodeloginlogic.go index 9ede239..a8d3aab 100644 --- a/app/main/api/internal/logic/user/mobilecodeloginlogic.go +++ b/app/main/api/internal/logic/user/mobilecodeloginlogic.go @@ -3,6 +3,7 @@ package user import ( "context" "database/sql" + stderrors "errors" "fmt" "os" "qnc-server/app/main/api/internal/svc" @@ -10,6 +11,7 @@ import ( "qnc-server/app/main/model" "qnc-server/common/xerr" "qnc-server/pkg/lzkit/crypto" + "strings" "time" "github.com/pkg/errors" @@ -44,7 +46,7 @@ func (l *MobileCodeLoginLogic) MobileCodeLogin(req *types.MobileCodeLoginReq) (r redisKey := fmt.Sprintf("%s:%s", "login", encryptedMobile) cacheCode, err := l.svcCtx.Redis.Get(redisKey) if err != nil { - if errors.Is(err, redis.Nil) { + if stderrors.Is(err, redis.Nil) { return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "手机登录, 验证码过期: %s", encryptedMobile) } return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取验证码redis缓存失败, mobile: %s, err: %+v", encryptedMobile, err) @@ -63,10 +65,28 @@ func (l *MobileCodeLoginLogic) MobileCodeLogin(req *types.MobileCodeLoginReq) (r l.Infof("手机登录, 用户不存在,自动注册新用户: %s", encryptedMobile) registeredUserID, registerErr := l.svcCtx.UserService.RegisterUser(l.ctx, encryptedMobile) if registerErr != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 自动注册用户失败, mobile: %s, err: %+v", encryptedMobile, registerErr) + // 检查是否是并发注册导致的唯一键冲突 + // MySQL错误码: 1062 (23000) - Duplicate entry + errStr := registerErr.Error() + if strings.Contains(errStr, "Duplicate entry") && strings.Contains(errStr, "user_auth.unique_type_key") { + // 并发冲突,重新查询用户 + l.Infof("手机登录, 检测到并发注册冲突,重新查询用户: %s", encryptedMobile) + user, retryErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true}) + if retryErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 并发冲突后重新查询用户失败, mobile: %s, err: %+v", encryptedMobile, retryErr) + } + if user == nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 并发冲突后仍未找到用户, mobile: %s", encryptedMobile) + } + userID = user.Id + l.Infof("手机登录, 并发冲突后获取到已注册用户, userId: %s, mobile: %s", userID, encryptedMobile) + } else { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 自动注册用户失败, mobile: %s, err: %+v", encryptedMobile, registerErr) + } + } else { + userID = registeredUserID + l.Infof("手机登录, 自动注册用户成功, userId: %s, mobile: %s", userID, encryptedMobile) } - userID = registeredUserID - l.Infof("手机登录, 自动注册用户成功, userId: %s, mobile: %s", userID, encryptedMobile) } else { if user.Disable == 1 { return nil, errors.Wrapf(xerr.NewErrCode(xerr.USER_DISABLED), "用户已被封禁") diff --git a/app/main/api/internal/service/apirequestService.go b/app/main/api/internal/service/apirequestService.go index 1afbaf4..d06da15 100644 --- a/app/main/api/internal/service/apirequestService.go +++ b/app/main/api/internal/service/apirequestService.go @@ -61,23 +61,23 @@ type APIResponseData struct { func (a *ApiRequestService) ProcessRequests(params []byte, productID string) ([]byte, error) { var ctx, cancel = context.WithCancel(context.Background()) defer cancel() - build := a.productFeatureModel.SelectBuilder().Where(squirrel.Eq{ - "product_id": productID, - }) + build := a.productFeatureModel.SelectBuilder().Where(squirrel.Eq{ + "product_id": productID, + }) productFeatureList, findProductFeatureErr := a.productFeatureModel.FindAll(ctx, build, "") if findProductFeatureErr != nil { return nil, findProductFeatureErr } - var featureIDs []string - isImportantMap := make(map[string]int64, len(productFeatureList)) + var featureIDs []string + isImportantMap := make(map[string]int64, len(productFeatureList)) for _, pf := range productFeatureList { - featureIDs = append(featureIDs, pf.FeatureId) - isImportantMap[pf.FeatureId] = pf.IsImportant + featureIDs = append(featureIDs, pf.FeatureId) + isImportantMap[pf.FeatureId] = pf.IsImportant } if len(featureIDs) == 0 { return nil, errors.New("featureIDs 是空的") } - builder := a.featureModel.SelectBuilder().Where(squirrel.Eq{"id": featureIDs}) + builder := a.featureModel.SelectBuilder().Where(squirrel.Eq{"id": featureIDs}) featureList, findFeatureErr := a.featureModel.FindAll(ctx, builder, "") if findFeatureErr != nil { return nil, findFeatureErr @@ -114,7 +114,7 @@ func (a *ApiRequestService) ProcessRequests(params []byte, productID string) ([] preprocessErr error ) // 若 isImportantMap[feature.ID] == 1,则表示需要在出错时重试 - isImportant := isImportantMap[feature.Id] == 1 + isImportant := isImportantMap[feature.Id] == 1 tryCount := 0 for { tryCount++ @@ -207,6 +207,7 @@ var requestProcessors = map[string]func(*ApiRequestService, []byte) ([]byte, err "IVYZ8I9J": (*ApiRequestService).ProcessIVYZ8I9JRequest, "JRZQ7F1A": (*ApiRequestService).ProcessJRZQ7F1ARequest, "IVYZ3P9M": (*ApiRequestService).ProcessIVYZ3P9MRequest, + "JRZQ6F2A": (*ApiRequestService).ProcessJRZQ6F2ARequest, } // PreprocessRequestApi 调用指定的请求处理函数 @@ -1577,3 +1578,26 @@ func (a *ApiRequestService) ProcessIVYZ3P9MRequest(params []byte) ([]byte, error return convertTianyuanResponse(resp) } + +// ProcessJRZQ6F2ARequest 借贷申请 +func (a *ApiRequestService) ProcessJRZQ6F2ARequest(params []byte) ([]byte, error) { + name := gjson.GetBytes(params, "name") + idCard := gjson.GetBytes(params, "id_card") + mobile := gjson.GetBytes(params, "mobile") + if !name.Exists() || !idCard.Exists() || !mobile.Exists() { + return nil, errors.New("api请求, JRZQ6F2A, 获取相关参数失败") + } + + resp, err := a.tianyuanapi.CallInterface("JRZQ6F2A", map[string]interface{}{ + "name": name.String(), + "id_card": idCard.String(), + "mobile_no": mobile.String(), + "authorized": "1", + }) + + if err != nil { + return nil, err + } + + return convertTianyuanResponse(resp) +}