pet-ai/server/plugin/wechat-integration/api/user/mini_user_api.go

277 lines
8.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package user
import (
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/wechat-integration/model/request"
wechatResponse "github.com/flipped-aurora/gin-vue-admin/server/plugin/wechat-integration/model/response"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/wechat-integration/service"
"github.com/flipped-aurora/gin-vue-admin/server/utils"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
type MiniUserApi struct{}
var miniService = service.ServiceGroupApp.MiniService
// Login 小程序登录
// @Tags WechatMiniUser
// @Summary 小程序登录
// @Description 微信小程序登录接口
// @Accept json
// @Produce json
// @Param data body request.MiniLoginRequest true "登录参数"
// @Success 200 {object} wechatResponse.Response{data=wechatResponse.MiniLoginResponse} "登录成功"
// @Router /wechat/user/mini/login [post]
func (w *MiniUserApi) Login(c *gin.Context) {
var req request.MiniLoginRequest
err := c.ShouldBindJSON(&req)
if err != nil {
c.JSON(200, wechatResponse.ErrorResponseWithMsg(wechatResponse.ERROR_PARAM_INVALID, err.Error()))
return
}
if req.Code == "" {
c.JSON(200, wechatResponse.ErrorResponse(wechatResponse.ERROR_PARAM_MISSING))
return
}
user, err := miniService.Code2Session(req.Code)
if err != nil {
global.GVA_LOG.Error("小程序登录失败!", zap.Error(err))
// 根据错误类型返回不同的错误码
if err.Error() == "获取用户 OpenID 失败" {
c.JSON(200, wechatResponse.ErrorResponse(wechatResponse.ERROR_WX_OPENID_EMPTY))
} else if err.Error() == "微信小程序 Code2Session 失败" {
c.JSON(200, wechatResponse.ErrorResponse(wechatResponse.ERROR_WX_SESSION_FAILED))
} else {
c.JSON(200, wechatResponse.ErrorResponseWithMsg(wechatResponse.ERROR_WX_CODE_INVALID, err.Error()))
}
return
}
// 生成JWT token
token, _, err := utils.AppUserLoginToken(user)
if err != nil {
global.GVA_LOG.Error("生成token失败!", zap.Error(err))
c.JSON(200, wechatResponse.ErrorResponseWithMsg(wechatResponse.ERROR_INTERNAL, "生成token失败"))
return
}
resp := wechatResponse.MiniLoginResponse{
OpenID: user.OpenID,
UnionID: user.UnionID,
Token: token,
}
c.JSON(200, wechatResponse.SuccessResponseWithMsg(resp, "登录成功"))
}
// GetUserInfo 获取用户信息
// @Tags WechatMiniUser
// @Summary 获取用户信息
// @Description 获取当前登录用户的详细信息
// @Accept json
// @Produce json
// @Success 200 {object} wechatResponse.Response{data=wechatResponse.MiniUserInfoResponse} "获取成功"
// @Router /user/wechat/mini/userinfo [get]
func (w *MiniUserApi) GetUserInfo(c *gin.Context) {
// 从JWT token中获取用户信息
claims, exists := c.Get("user_claims")
if !exists {
c.JSON(200, wechatResponse.ErrorResponse(wechatResponse.ERROR_UNAUTHORIZED))
return
}
userClaims, ok := claims.(*systemReq.AppUserClaims)
if !ok {
c.JSON(200, wechatResponse.ErrorResponse(wechatResponse.ERROR_TOKEN_INVALID))
return
}
openid := userClaims.AppBaseClaims.OpenID
if openid == "" {
c.JSON(200, wechatResponse.ErrorResponse(wechatResponse.ERROR_WX_OPENID_EMPTY))
return
}
user, err := miniService.GetUserInfo(openid)
if err != nil {
global.GVA_LOG.Error("获取用户信息失败!", zap.Error(err))
if err.Error() == "用户不存在" {
c.JSON(200, wechatResponse.ErrorResponse(wechatResponse.ERROR_USER_NOT_FOUND))
} else {
c.JSON(200, wechatResponse.ErrorResponseWithMsg(wechatResponse.ERROR_INTERNAL, err.Error()))
}
return
}
// 构造响应数据
resp := wechatResponse.MiniUserInfoResponse{
ID: user.ID,
OpenID: user.OpenID,
UnionID: user.UnionID,
NickName: user.Nickname,
Avatar: user.AvatarURL,
Phone: user.Phone,
Gender: user.Gender,
City: user.City,
Province: user.Province,
Country: user.Country,
CreateTime: user.CreatedAt.Format("2006-01-02 15:04:05"),
UpdateTime: user.UpdatedAt.Format("2006-01-02 15:04:05"),
}
c.JSON(200, wechatResponse.SuccessResponseWithMsg(resp, "获取成功"))
}
// UpdateUserInfo 更新用户信息
// @Tags WechatMiniUser
// @Summary 更新用户信息
// @Description 更新小程序用户信息
// @Accept json
// @Produce json
// @Param data body request.UpdateUserInfoRequest true "用户信息"
// @Success 200 {object} response.Response "更新成功"
// @Router /wechat/user/mini/userinfo [put]
func (w *MiniUserApi) UpdateUserInfo(c *gin.Context) {
var req request.UpdateUserInfoRequest
err := c.ShouldBindJSON(&req)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
if req.OpenID == "" {
response.FailWithMessage("openid不能为空", c)
return
}
err = miniService.UpdateUserInfo(req.OpenID, req.UserInfo)
if err != nil {
global.GVA_LOG.Error("更新用户信息失败!", zap.Error(err))
response.FailWithMessage("更新失败: "+err.Error(), c)
return
}
response.OkWithMessage("更新成功", c)
}
// BindPhone 绑定手机号
// @Tags WechatMiniUser
// @Summary 绑定手机号
// @Description 绑定手机号并关联系统用户
// @Accept json
// @Produce json
// @Param data body request.BindPhoneRequest true "绑定参数"
// @Success 200 {object} response.Response{data=model.WechatMiniUser} "绑定成功"
// @Router /wechat/user/mini/bind-phone [post]
func (w *MiniUserApi) BindPhone(c *gin.Context) {
var req request.BindPhoneRequest
err := c.ShouldBindJSON(&req)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
if req.OpenID == "" || req.Phone == "" {
response.FailWithMessage("openid和手机号不能为空", c)
return
}
user, err := miniService.BindPhone(req.OpenID, req.Phone)
if err != nil {
global.GVA_LOG.Error("绑定手机号失败!", zap.Error(err))
response.FailWithMessage("绑定失败: "+err.Error(), c)
return
}
response.OkWithDetailed(user, "绑定成功", c)
}
// UpdatePhoneNumber 更新用户手机号
// @Tags WechatMiniUser
// @Summary 更新用户手机号
// @Description 通过微信手机号授权更新用户手机号
// @Accept json
// @Produce json
// @Param data body request.WxPhoneLoginRequest true "手机号授权参数"
// @Success 200 {object} response.Response{data=string} "更新成功"
// @Router /user/wechat/mini/phone-update [post]
func (w *MiniUserApi) UpdatePhoneNumber(c *gin.Context) {
var req request.WxPhoneLoginRequest
err := c.ShouldBindJSON(&req)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
if req.EncryptedData == "" || req.IV == "" {
response.FailWithMessage("encryptedData和iv不能为空", c)
return
}
// 从 JWT token 中获取用户信息
claims, exists := c.Get("user_claims")
if !exists {
response.FailWithMessage("获取用户信息失败", c)
return
}
// 获取当前用户的信息
userClaims, ok := claims.(*systemReq.AppUserClaims)
if !ok {
response.FailWithMessage("用户信息格式错误", c)
return
}
// 直接从 claims 中获取 openid
openid := userClaims.AppBaseClaims.OpenID
if openid == "" {
response.FailWithMessage("用户 OpenID 不存在", c)
return
}
phoneNumber, err := miniService.UpdatePhoneByEncryption(openid, req.EncryptedData, req.IV)
if err != nil {
global.GVA_LOG.Error("更新手机号失败!", zap.Error(err))
response.FailWithMessage("更新失败: "+err.Error(), c)
return
}
response.OkWithDetailed(phoneNumber, "手机号更新成功", c)
}
// CheckUnionID 检查UnionID是否存在为APP登录预留
// @Tags WechatMiniUser
// @Summary 检查UnionID
// @Description 检查UnionID是否已存在用户
// @Accept json
// @Produce json
// @Param unionid query string true "UnionID"
// @Success 200 {object} response.Response{data=model.WechatMiniUser} "检查成功"
// @Router /wechat/user/mini/check-unionid [get]
func (w *MiniUserApi) CheckUnionID(c *gin.Context) {
unionid := c.Query("unionid")
if unionid == "" {
response.FailWithMessage("unionid不能为空", c)
return
}
user, err := miniService.CheckUnionIDExists(unionid)
if err != nil {
global.GVA_LOG.Error("检查UnionID失败!", zap.Error(err))
response.FailWithMessage("检查失败: "+err.Error(), c)
return
}
if user == nil {
response.OkWithDetailed(nil, "UnionID不存在", c)
} else {
response.OkWithDetailed(user, "UnionID已存在", c)
}
}