f
This commit is contained in:
@@ -1,11 +1,14 @@
|
|||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"tyc-server/app/main/api/internal/logic/user"
|
"tyc-server/app/main/api/internal/logic/user"
|
||||||
"tyc-server/app/main/api/internal/svc"
|
"tyc-server/app/main/api/internal/svc"
|
||||||
"tyc-server/app/main/api/internal/types"
|
"tyc-server/app/main/api/internal/types"
|
||||||
|
jwtx "tyc-server/common/jwt"
|
||||||
"tyc-server/common/result"
|
"tyc-server/common/result"
|
||||||
"tyc-server/pkg/lzkit/validator"
|
"tyc-server/pkg/lzkit/validator"
|
||||||
|
|
||||||
@@ -23,7 +26,14 @@ func WxH5AuthHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
|||||||
result.ParamValidateErrorResult(r, w, err)
|
result.ParamValidateErrorResult(r, w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
l := user.NewWxH5AuthLogic(r.Context(), svcCtx)
|
ctx := r.Context()
|
||||||
|
// 本路由未挂 AuthInterceptor;若前端已带登录态(如手机号登录后再走静默授权),需解析 JWT 以便把 openid 写入当前正式用户 user_auth
|
||||||
|
if authHeader := strings.TrimSpace(r.Header.Get("Authorization")); authHeader != "" {
|
||||||
|
if claims, err := jwtx.ParseJwtToken(authHeader, svcCtx.Config.JwtAuth.AccessSecret); err == nil {
|
||||||
|
ctx = context.WithValue(ctx, jwtx.ExtraKey, claims)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l := user.NewWxH5AuthLogic(ctx, svcCtx)
|
||||||
resp, err := l.WxH5Auth(&req)
|
resp, err := l.WxH5Auth(&req)
|
||||||
result.HttpResult(r, w, resp, err)
|
result.HttpResult(r, w, resp, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"tyc-server/app/main/model"
|
"tyc-server/app/main/model"
|
||||||
|
"tyc-server/common/ctxdata"
|
||||||
"tyc-server/common/xerr"
|
"tyc-server/common/xerr"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@@ -39,6 +41,11 @@ func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthRe
|
|||||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取access_token失败: %v", err)
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取access_token失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 已登录正式用户 + 静默授权 code:把当前公众号 openid 写入 user_auth(wxh5_openid),供微信内 JSAPI 支付使用
|
||||||
|
if claims, claimsErr := ctxdata.GetClaimsFromCtx(l.ctx); claimsErr == nil && claims != nil && claims.UserType == model.UserTypeNormal {
|
||||||
|
return l.bindWxh5OpenidToNormalUser(claims.UserId, accessTokenResp.Openid)
|
||||||
|
}
|
||||||
|
|
||||||
// Step 2: 查找用户授权信息
|
// Step 2: 查找用户授权信息
|
||||||
userAuth, findErr := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, model.UserAuthTypeWxh5OpenID, accessTokenResp.Openid)
|
userAuth, findErr := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, model.UserAuthTypeWxh5OpenID, accessTokenResp.Openid)
|
||||||
if findErr != nil && !errors.Is(findErr, model.ErrNotFound) {
|
if findErr != nil && !errors.Is(findErr, model.ErrNotFound) {
|
||||||
@@ -94,6 +101,53 @@ func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthRe
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bindWxh5OpenidToNormalUser 将 snsapi_base 换得的 openid 绑定到当前正式用户(插入或更新 user_auth)。
|
||||||
|
// 临时用户不能走此分支:需在绑定手机号时由 TempUserBindUser 写入 user_auth,避免与临时转正逻辑冲突。
|
||||||
|
func (l *WxH5AuthLogic) bindWxh5OpenidToNormalUser(normalUserID int64, openid string) (*types.WXH5AuthResp, error) {
|
||||||
|
openid = strings.TrimSpace(openid)
|
||||||
|
if openid == "" {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "微信 openid 为空")
|
||||||
|
}
|
||||||
|
existingByOpenid, err := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, model.UserAuthTypeWxh5OpenID, openid)
|
||||||
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询 wxh5_openid 失败: %v", err)
|
||||||
|
}
|
||||||
|
if existingByOpenid != nil && existingByOpenid.UserId != normalUserID {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg("该微信已绑定其他账号"), "wxh5_openid 已被占用 user_id=%d", existingByOpenid.UserId)
|
||||||
|
}
|
||||||
|
rowByUser, err := l.svcCtx.UserAuthModel.FindOneByUserIdAuthType(l.ctx, normalUserID, model.UserAuthTypeWxh5OpenID)
|
||||||
|
if errors.Is(err, model.ErrNotFound) {
|
||||||
|
_, insErr := l.svcCtx.UserAuthModel.Insert(l.ctx, nil, &model.UserAuth{
|
||||||
|
UserId: normalUserID,
|
||||||
|
AuthType: model.UserAuthTypeWxh5OpenID,
|
||||||
|
AuthKey: openid,
|
||||||
|
})
|
||||||
|
if insErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "写入 wxh5_openid 失败: %v", insErr)
|
||||||
|
}
|
||||||
|
logx.WithContext(l.ctx).Infof("[WxH5Auth] 已写入 user_auth wxh5_openid user_id=%d", normalUserID)
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询用户 wxh5_openid 失败: %v", err)
|
||||||
|
} else if rowByUser.AuthKey != openid {
|
||||||
|
rowByUser.AuthKey = openid
|
||||||
|
if _, updErr := l.svcCtx.UserAuthModel.Update(l.ctx, nil, rowByUser); updErr != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新 wxh5_openid 失败: %v", updErr)
|
||||||
|
}
|
||||||
|
logx.WithContext(l.ctx).Infof("[WxH5Auth] 已更新 user_auth wxh5_openid user_id=%d", normalUserID)
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, normalUserID, model.UserTypeNormal)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成JWT token失败: %v", err)
|
||||||
|
}
|
||||||
|
now := time.Now().Unix()
|
||||||
|
return &types.WXH5AuthResp{
|
||||||
|
AccessToken: token,
|
||||||
|
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
|
||||||
|
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type AccessTokenResp struct {
|
type AccessTokenResp struct {
|
||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
Openid string `json:"openid"`
|
Openid string `json:"openid"`
|
||||||
|
|||||||
Reference in New Issue
Block a user