auth.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package auth
  2. import (
  3. "Cold_Logistic/internal/pkg/common/codex"
  4. "Cold_Logistic/internal/pkg/common/constant"
  5. "Cold_Logistic/internal/pkg/common/global"
  6. "Cold_Logistic/internal/pkg/common/options"
  7. "Cold_Logistic/internal/server/adapter/http/middleware"
  8. "Cold_Logistic/internal/server/application/authsrv"
  9. "Cold_Logistic/internal/server/infra/dao"
  10. "encoding/json"
  11. "fmt"
  12. "github.com/gin-gonic/gin"
  13. "github.com/skip2/go-qrcode"
  14. "gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/core"
  15. "gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/errors"
  16. "net/http"
  17. "net/url"
  18. )
  19. func Register(r *gin.RouterGroup) {
  20. api := NewApi()
  21. // 小程序登录
  22. r.POST("/auth/login", api.login)
  23. r.POST("/auth/wechatLogin", api.wechatLogin)
  24. r.POST("/auth/wechatCallback", api.wechatCallBack)
  25. r.POST("/auth/loginOut", middleware.Auth(), api.LoginOut)
  26. return
  27. }
  28. type Api struct{}
  29. func NewApi() Api {
  30. return Api{}
  31. }
  32. // Login 登录
  33. func (api Api) login(c *gin.Context) {
  34. req := authsrv.LoginReqVo{}
  35. if err := c.ShouldBindJSON(&req); err != nil {
  36. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrBindJSON, ""))
  37. return
  38. }
  39. err := req.Validate()
  40. if err != nil {
  41. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrParamValidate, ""))
  42. return
  43. }
  44. srv := authsrv.NewAuthService(dao.NewDataStore(global.CommonConnectRepoInst.StoreDB))
  45. var res authsrv.LoginRespVo
  46. switch req.LoginType {
  47. case constant.AccountPlatform:
  48. res, err = srv.PlatformLogin(c, req)
  49. if err != nil {
  50. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrSystemSrv, ""))
  51. return
  52. }
  53. case constant.AccountApplet:
  54. res, err = srv.UserLogin(c, req)
  55. if err != nil {
  56. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrSystemSrv, ""))
  57. return
  58. }
  59. }
  60. core.WriteResponse(c, nil, res)
  61. }
  62. // wechatLogin 微信扫码登录
  63. func (api Api) wechatLogin(c *gin.Context) {
  64. appId := options.OptInstance.Wechat.AppId
  65. state := "" //防止跨站请求伪造攻击 增加安全性
  66. redirectURL := url.QueryEscape(options.OptInstance.Wechat.RedirectUri) //userinfo,
  67. wechatLoginURL := fmt.Sprintf("https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&state=%s&scope=snsapi_userinfo#wechat_redirect", appId, redirectURL, state)
  68. wechatLoginURL, _ = url.QueryUnescape(wechatLoginURL)
  69. // 生成二维码
  70. qrCode, err := qrcode.Encode(wechatLoginURL, qrcode.Medium, 256)
  71. if err != nil {
  72. // 错误处理
  73. c.String(http.StatusInternalServerError, "Error generating QR code")
  74. return
  75. }
  76. // c.Redirect(http.StatusTemporaryRedirect, wechatLoginURL)
  77. head := map[string]string{
  78. "Content-Type": "image/png",
  79. }
  80. // 将二维码图片作为响应返回给用户
  81. core.WriteBytesResponse(c, nil, qrCode, head)
  82. }
  83. func (api Api) wechatCallBack(c *gin.Context) {
  84. // 获取微信返回的授权码
  85. code := c.Query("code")
  86. appId := options.OptInstance.Wechat.AppId
  87. appSecret := options.OptInstance.Wechat.AppSecret
  88. // 向微信服务器发送请求,获取access_token和openid
  89. tokenResp, err := http.Get(fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", appId, appSecret, code))
  90. if err != nil {
  91. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrParamValidate, "error,获取token失败"))
  92. return
  93. }
  94. // 解析响应中的access_token和openid
  95. var tokenData struct {
  96. AccessToken string `json:"access_token"`
  97. ExpiresIn int `json:"expires_in"`
  98. RefreshToken string `json:"refresh_token"`
  99. OpenID string `json:"openid"`
  100. Scope string `json:"scope"`
  101. }
  102. if err1 := json.NewDecoder(tokenResp.Body).Decode(&tokenData); err1 != nil {
  103. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrParamValidate, "error,获取token失败"))
  104. return
  105. }
  106. userInfoURL := fmt.Sprintf("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s", tokenData.AccessToken, tokenData.OpenID)
  107. userInfoResp, err := http.Get(userInfoURL)
  108. defer userInfoResp.Body.Close()
  109. if err != nil {
  110. // 错误处理
  111. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrParamValidate, "获取失败"))
  112. return
  113. }
  114. //------------------------------------
  115. var userData struct {
  116. OpenID string `json:"openid"`
  117. Nickname string `json:"nickname"`
  118. }
  119. if err1 := json.NewDecoder(userInfoResp.Body).Decode(&userData); err1 != nil {
  120. // 错误处理
  121. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrParamValidate, "获取用户信息失败"))
  122. return
  123. }
  124. req := authsrv.LoginReqVo{
  125. LoginType: constant.AccountApplet,
  126. Openid: userData.OpenID,
  127. NickName: userData.Nickname,
  128. }
  129. srv := authsrv.NewAuthService(dao.NewDataStore(global.CommonConnectRepoInst.StoreDB))
  130. res, err := srv.UserLogin(c, req)
  131. if err != nil {
  132. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrSystemSrv, ""))
  133. return
  134. }
  135. core.WriteResponse(c, nil, res)
  136. }
  137. func (api Api) LoginOut(c *gin.Context) {
  138. srv := authsrv.NewAuthService(dao.NewDataStore(global.CommonConnectRepoInst.StoreDB))
  139. err := srv.LoginOut(c)
  140. if err != nil {
  141. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrSystemSrv, ""))
  142. return
  143. }
  144. core.WriteResponse(c, nil, "success")
  145. }