This commit is contained in:
wucongxing8150 2024-07-19 13:37:16 +08:00
parent ec88138888
commit dfda2e2425
11 changed files with 313 additions and 30 deletions

1
.gitignore vendored
View File

@ -18,3 +18,4 @@
.idea/
.git/
.DS_Store/
.tmp/

View File

@ -1,12 +1,18 @@
package controller
import (
"fmt"
"github.com/gin-gonic/gin"
"hepa-calc-api/api/dao"
"hepa-calc-api/api/model"
"hepa-calc-api/api/requests"
"hepa-calc-api/api/responses"
"hepa-calc-api/api/service"
"hepa-calc-api/extend/weChat"
"hepa-calc-api/global"
"hepa-calc-api/utils"
"strconv"
"time"
)
type Login struct{}
@ -29,6 +35,18 @@ func (r *Login) LoginPhone(c *gin.Context) {
// LoginWx 微信授权登录
func (r *Login) LoginWx(c *gin.Context) {
userService := service.UserService{}
// 处理用户头像
avatar, err := userService.HandleUserAvatar("https://thirdwx.qlogo.cn/mmopen/vi_32/dzhWq43iaB5GyJJUbajibSQtIt6d4Y9QPk5ImB1C14fPk6AOtcgaPztUzjKwb9kmPtqNpyCal5cEyw0YyTr1QEbdtHiaOViay4RgSpdm2XaduXA/132")
if err != nil {
responses.FailWithMessage(err.Error(), c)
return
}
fmt.Println(avatar)
responses.Ok(c)
return
loginRequest := requests.LoginRequest{}
req := loginRequest.LoginWx
if err := c.ShouldBind(&req); err != nil {
@ -42,5 +60,88 @@ func (r *Login) LoginWx(c *gin.Context) {
return
}
responses.Ok(c)
// 获取微信网页授权access_token
webAccessToken, err := weChat.GetWebAccessToken(req.Code)
if err != nil {
responses.FailWithMessage(err.Error(), c)
return
}
fmt.Println(webAccessToken)
// 网页授权拉取用户信息
userInfo, err := weChat.GetUserInfo(webAccessToken.AccessToken, webAccessToken.OpenId)
if err != nil {
responses.FailWithMessage(err.Error(), c)
return
}
fmt.Println(userInfo)
// 检测用户信息
userDao := dao.UserDao{}
maps := make(map[string]interface{})
maps["open_id"] = webAccessToken.OpenId
user, _ := userDao.GetUser(maps)
// 新用户处理方式
if user == nil {
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
userService := service.UserService{}
// 处理用户头像
avatar, err := userService.HandleUserAvatar(userInfo.HeadImgUrl)
if err != nil {
tx.Rollback()
responses.FailWithMessage(err.Error(), c)
return
}
// 新增用户
user := &model.User{
UserName: userInfo.Nickname,
Mobile: "",
RegisterSource: req.Source,
OpenId: userInfo.OpenId,
UnionId: userInfo.UnionId,
Age: nil,
Sex: userInfo.Sex,
Avatar: avatar,
IsMember: 0,
MemberExpireDate: nil,
LoginAt: model.LocalTime(time.Now()),
LoginIp: req.LoginIp,
}
user, err = userDao.AddUser(tx, user)
if err != nil {
tx.Rollback()
responses.FailWithMessage(err.Error(), c)
return
}
// 获取app用户信息
var result *string
if result == nil {
// 新增app用户信息
}
tx.Commit()
}
// 下发token
token := &utils.Token{
UserId: fmt.Sprintf("%d", user.UserId),
}
// 生成jwt
jwt, err := token.NewJWT()
if err != nil {
responses.FailWithMessage("登陆失败", c)
return
}
responses.OkWithData(jwt, c)
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"hepa-calc-api/api/model"
"hepa-calc-api/utils"
"time"
)
// UserDto 用户表
@ -19,7 +20,7 @@ type UserDto struct {
Sex uint `json:"sex"` // 性别0:未知 1:男 2:女)
Avatar string `json:"avatar"` // 头像
IsMember int `json:"is_member"` // 是否会员0:否 1:是)
MemberExpireDate model.LocalTime `json:"member_expire_date"` // 会员到期时间非会员时为null
MemberExpireDate *time.Time `json:"member_expire_date"` // 会员到期时间非会员时为null
LoginAt model.LocalTime `json:"login_at"` // 登陆时间
LoginIp string `json:"login_ip"` // 登陆ip
CreatedAt model.LocalTime `json:"created_at"` // 创建时间
@ -34,8 +35,8 @@ func GetUserDto(m *model.User) *UserDto {
Mobile: m.Mobile,
UserStatus: m.UserStatus,
RegisterSource: m.RegisterSource,
Age: m.Age,
Sex: m.Sex,
Age: *m.Age,
Sex: uint(m.Sex),
Avatar: utils.AddOssDomain(m.Avatar),
IsMember: m.IsMember,
MemberExpireDate: m.MemberExpireDate,

View File

@ -8,20 +8,20 @@ import (
// User 用户表
type User struct {
UserId int64 `gorm:"column:user_id;type:bigint(19);primary_key;comment:用户id" json:"user_id"`
UserName string `gorm:"column:user_name;type:varchar(200);comment:用户名称" json:"user_name"`
Mobile string `gorm:"column:mobile;type:varchar(20);comment:手机号;NOT NULL" json:"mobile"`
UserStatus int `gorm:"column:user_status;type:tinyint(1);default:1;comment:状态1:正常 2:禁用)" json:"user_status"`
RegisterSource int `gorm:"column:register_source;type:tinyint(1);default:1;comment:注册来源1app注册 2公众号注册" json:"register_source"`
OpenId string `gorm:"column:open_id;type:varchar(100);comment:用户微信标识" json:"open_id"`
UnionId string `gorm:"column:union_id;type:varchar(100);comment:微信开放平台标识" json:"union_id"`
Age uint `gorm:"column:age;type:int(10) unsigned;comment:年龄" json:"age"`
Sex uint `gorm:"column:sex;type:tinyint(1) unsigned;default:0;comment:性别0:未知 1:男 2:女)" json:"sex"`
Avatar string `gorm:"column:avatar;type:varchar(255);comment:头像" json:"avatar"`
IsMember int `gorm:"column:is_member;type:tinyint(1);default:0;comment:是否会员0:否 1:是)" json:"is_member"`
MemberExpireDate LocalTime `gorm:"column:member_expire_date;type:datetime;comment:会员到期时间非会员时为null" json:"member_expire_date"`
LoginAt LocalTime `gorm:"column:login_at;type:datetime;comment:登陆时间" json:"login_at"`
LoginIp string `gorm:"column:login_ip;type:varchar(255);comment:登陆ip" json:"login_ip"`
UserId int64 `gorm:"column:user_id;type:bigint(19);primary_key;comment:用户id" json:"user_id"`
UserName string `gorm:"column:user_name;type:varchar(200);comment:用户名称" json:"user_name"`
Mobile string `gorm:"column:mobile;type:varchar(20);comment:手机号;NOT NULL" json:"mobile"`
UserStatus int `gorm:"column:user_status;type:tinyint(1);default:1;comment:状态1:正常 2:禁用)" json:"user_status"`
RegisterSource int `gorm:"column:register_source;type:tinyint(1);default:1;comment:注册来源1app注册 2公众号注册" json:"register_source"`
OpenId string `gorm:"column:open_id;type:varchar(100);comment:用户微信标识" json:"open_id"`
UnionId string `gorm:"column:union_id;type:varchar(100);comment:微信开放平台标识" json:"union_id"`
Age *uint `gorm:"column:age;type:int(10) unsigned;comment:年龄" json:"age"`
Sex int `gorm:"column:sex;type:tinyint(1) unsigned;default:0;comment:性别0:未知 1:男 2:女)" json:"sex"`
Avatar string `gorm:"column:avatar;type:varchar(255);comment:头像" json:"avatar"`
IsMember int `gorm:"column:is_member;type:tinyint(1);default:0;comment:是否会员0:否 1:是)" json:"is_member"`
MemberExpireDate *time.Time `gorm:"column:member_expire_date;type:datetime;comment:会员到期时间非会员时为null" json:"member_expire_date"`
LoginAt LocalTime `gorm:"column:login_at;type:datetime;comment:登陆时间" json:"login_at"`
LoginIp string `gorm:"column:login_ip;type:varchar(255);comment:登陆ip" json:"login_ip"`
Model
}

View File

@ -6,5 +6,7 @@ type LoginRequest struct {
// LoginWx 微信授权登录
type LoginWx struct {
Code string `json:"code" form:"code" label:"授权码"`
Code string `json:"code" form:"code" label:"授权码"`
Source int `json:"source" form:"source" label:"来源1app 2公众号"`
LoginIp string `json:"login_ip" form:"login_ip" label:"登录ip"`
}

View File

@ -78,11 +78,8 @@ func publicRouter(r *gin.Engine, api controller.Api) {
// 手机号登录
loginGroup.POST("/phone", api.Login.LoginPhone)
wxGroup := loginGroup.Group("/wx")
{
// 微信授权登录
wxGroup.POST("", api.Login.LoginWx)
}
// 微信授权登录
loginGroup.POST("/wx", api.Login.LoginWx)
}
// 验证码

View File

@ -1,4 +1,41 @@
package service
import (
"fmt"
"hepa-calc-api/extend/aliyun"
"hepa-calc-api/utils"
"math/rand"
"time"
)
type UserService struct {
}
// HandleUserAvatar 处理用户头像
func (r *UserService) HandleUserAvatar(wxAvatar string) (avatar string, err error) {
if wxAvatar == "" {
return "", nil
}
// 下载文件到内存
ram, err := aliyun.GetObjectToRAM(wxAvatar)
if err != nil {
return "", err
}
// 设置文件名字
now := time.Now()
dateTimeString := now.Format("20060102150405") // 当前时间字符串
rand.New(rand.NewSource(time.Now().UnixNano())) // 设置随机数
ossPath := "/test/医生账户" + dateTimeString + fmt.Sprintf("%d", rand.Intn(9000)+1000) + ".png"
// 上传oss
_, err = aliyun.PutObjectByte(ossPath, []byte(ram))
if err != nil {
return "", err
}
ossPath = utils.AddOssDomain("/" + ossPath)
return ossPath, nil
}

View File

@ -47,8 +47,8 @@ dysms:
# [微信]
wechat:
app-id: wxa2ab38f49998a990
app-secret: 2671d2f4285180ddec5a5a2b16ed50f2
app-id: wxc8ac5051745bc795
app-secret: 678b63a8a7541e528abc3040c3cea809
pay-notify-url: callback/wxpay/inquiry/success
refund-notify-url: callback/wxpay/inquiry/refund
refund-notify-domain: https://dev.hospital.applets.igandanyiyuan.com/

View File

@ -1,10 +1,10 @@
package config
type Wechat struct {
AppId string `mapstructure:"patient-app-id" json:"patient-app-id" yaml:"patient-app-id"`
AppSecret string `mapstructure:"patient-app-secret" json:"patient-app-secret" yaml:"patient-app-secret"`
PayNotifyUrl string `mapstructure:"patient-inquiry-pay-notify-url" json:"patient-inquiry-pay-notify-url" yaml:"patient-inquiry-pay-notify-url"`
RefundNotifyUrl string `mapstructure:"patient-inquiry-refund-notify-url" json:"patient-inquiry-refund-notify-url" yaml:"patient-inquiry-refund-notify-url"`
AppId string `mapstructure:"app-id" json:"app-id" yaml:"patient-app-id"`
AppSecret string `mapstructure:"app-secret" json:"app-secret" yaml:"app-secret"`
PayNotifyUrl string `mapstructure:"pay-notify-url" json:"pay-notify-url" yaml:"pay-notify-url"`
RefundNotifyUrl string `mapstructure:"refund-notify-url" json:"refund-notify-url" yaml:"refund-notify-url"`
Pay1636644248 Pay1636644248 `mapstructure:"pay-1636644248" json:"pay-1636644248" yaml:"pay-1636644248"`
}

76
extend/weChat/userInfo.go Normal file
View File

@ -0,0 +1,76 @@
package weChat
import (
"encoding/json"
"errors"
"io"
"net/http"
)
// GetUserInfoResponse 网页授权拉取用户信息返回值
type GetUserInfoResponse struct {
OpenId string `json:"openid" form:"openid" label:"openid"`
Nickname string `json:"nickname" form:"nickname" label:"用户昵称"`
Sex int `json:"sex" form:"sex" label:"性别"` // 用户的性别值为1时是男性值为2时是女性值为0时是未知
Province string `json:"province" form:"province" label:"省份"`
City string `json:"city" form:"city" label:"城市"`
Country string `json:"country" form:"country" label:"国家"`
HeadImgUrl string `json:"headimgurl" form:"headimgurl" label:"头像"`
UnionId string `json:"unionid" form:"unionid" label:"unionid"`
Errcode *int `json:"errcode" form:"errcode" label:"errcode"`
Errmsg string `json:"errmsg" form:"errmsg" label:"errmsg"`
}
// GetUserInfo 网页授权拉取用户信息
func GetUserInfo(accessToken, openId string) (r *GetUserInfoResponse, err error) {
if accessToken == "" {
return nil, errors.New("授权失败")
}
if openId == "" {
return nil, errors.New("授权失败")
}
// 拼接请求数据
requestUrl := "https://api.weixin.qq.com/sns/userinfo?" +
"access_token=" + accessToken +
"&openid=" + openId +
"&lang=zh_CN"
// 发送GET请求
resp, err := http.Get(requestUrl)
if err != nil {
return nil, err
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
if resp.StatusCode != 200 {
return nil, errors.New("请求失败")
}
// 读取响应体
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var response GetUserInfoResponse
err = json.Unmarshal([]byte(respBody), &response)
if err != nil {
// json解析失败
return nil, err
}
if response.Errcode != nil {
if response.Errmsg != "" {
return nil, errors.New(response.Errmsg)
} else {
return nil, errors.New("请求失败")
}
}
return &response, err
}

View File

@ -0,0 +1,68 @@
package weChat
import (
"encoding/json"
"errors"
"hepa-calc-api/config"
"io"
"net/http"
)
// GetWebAccessTokenResponse 获取网页授权access_token返回值
type GetWebAccessTokenResponse struct {
AccessToken string `json:"access_token" form:"access_token" label:"网页授权接口调用凭证"`
ExpiresIn int `json:"expires_in" form:"expires_in" label:"access_token接口调用凭证超时时间"`
RefreshToken string `json:"refresh_token" form:"refresh_token" label:"用户刷新access_token"`
OpenId string `json:"openid" form:"openid" label:"openid"`
Scope string `json:"scope" form:"scope" label:"scope"`
UnionId string `json:"unionid" form:"unionid" label:"unionid"`
Errcode *int `json:"errcode" form:"errcode" label:"errcode"`
Errmsg string `json:"errmsg" form:"errmsg" label:"errmsg"`
}
// GetWebAccessToken 获取网页授权access_token
func GetWebAccessToken(code string) (r *GetWebAccessTokenResponse, err error) {
// 拼接请求数据
requestUrl := "https://api.weixin.qq.com/sns/oauth2/access_token?" +
"appid=" + config.C.Wechat.AppId +
"&secret=" + config.C.Wechat.AppSecret +
"&code=" + code +
"&grant_type=authorization_code"
// 发送GET请求
resp, err := http.Get(requestUrl)
if err != nil {
return nil, err
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
if resp.StatusCode != 200 {
return nil, errors.New("请求失败")
}
// 读取响应体
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var response GetWebAccessTokenResponse
err = json.Unmarshal([]byte(respBody), &response)
if err != nil {
// json解析失败
return nil, err
}
if response.Errcode != nil {
if response.Errmsg != "" {
return nil, errors.New(response.Errmsg)
} else {
return nil, errors.New("请求失败")
}
}
return &response, err
}