f
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"tyc-server/app/main/api/internal/logic/user"
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-server/app/main/api/internal/types"
|
||||
jwtx "tyc-server/common/jwt"
|
||||
"tyc-server/common/result"
|
||||
"tyc-server/pkg/lzkit/validator"
|
||||
|
||||
@@ -23,7 +26,14 @@ func WxH5AuthHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
result.ParamValidateErrorResult(r, w, err)
|
||||
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)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
"tyc-server/app/main/model"
|
||||
"tyc-server/common/ctxdata"
|
||||
"tyc-server/common/xerr"
|
||||
|
||||
"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)
|
||||
}
|
||||
|
||||
// 已登录正式用户 + 静默授权 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: 查找用户授权信息
|
||||
userAuth, findErr := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, model.UserAuthTypeWxh5OpenID, accessTokenResp.Openid)
|
||||
if findErr != nil && !errors.Is(findErr, model.ErrNotFound) {
|
||||
@@ -94,6 +101,53 @@ func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthRe
|
||||
}, 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 {
|
||||
AccessToken string `json:"access_token"`
|
||||
Openid string `json:"openid"`
|
||||
|
||||
Reference in New Issue
Block a user