auth.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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. // @Tags 登录
  34. // @BasePath /clodLogistic/app/api/v1
  35. // @Summary 小程序登录
  36. // @Success 200 {object} authsrv.LoginRespVo
  37. // @Param req body authsrv.LoginReqVo true "登录"
  38. // @Accept application/json
  39. // @Authorization Bearer
  40. // @Router /app/auth/login [post]
  41. func (api Api) login(c *gin.Context) {
  42. req := authsrv.LoginReqVo{}
  43. if err := c.ShouldBindJSON(&req); err != nil {
  44. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrBindJSON, ""))
  45. return
  46. }
  47. err := req.Validate()
  48. if err != nil {
  49. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrParamValidate, ""))
  50. return
  51. }
  52. srv := authsrv.NewAuthService(dao.NewDataStore(global.CommonConnectRepoInst.StoreDB))
  53. var res authsrv.LoginRespVo
  54. switch req.LoginType {
  55. case constant.AccountPlatform:
  56. res, err = srv.PlatformLogin(c, req)
  57. if err != nil {
  58. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrSystemSrv, ""))
  59. return
  60. }
  61. case constant.AccountApplet:
  62. res, err = srv.UserLogin(c, req)
  63. if err != nil {
  64. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrSystemSrv, ""))
  65. return
  66. }
  67. }
  68. core.WriteResponse(c, nil, res)
  69. }
  70. // wechatLogin
  71. // @Tags 登录
  72. // @BasePath /clodLogistic/app/api/v1
  73. // @Summary 微信扫码登录
  74. // @Success 200 {object} authsrv.LoginRespVo
  75. // @Accept application/json
  76. // @Authorization Bearer
  77. // @Router /app/auth/wechatLogin [post]
  78. func (api Api) wechatLogin(c *gin.Context) {
  79. appId := options.OptInstance.Wechat.AppId
  80. state := "" //防止跨站请求伪造攻击 增加安全性
  81. redirectURL := url.QueryEscape(options.OptInstance.Wechat.RedirectUri) //userinfo,
  82. 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)
  83. wechatLoginURL, _ = url.QueryUnescape(wechatLoginURL)
  84. // 生成二维码
  85. qrCode, err := qrcode.Encode(wechatLoginURL, qrcode.Medium, 256)
  86. if err != nil {
  87. // 错误处理
  88. c.String(http.StatusInternalServerError, "Error generating QR code")
  89. return
  90. }
  91. // c.Redirect(http.StatusTemporaryRedirect, wechatLoginURL)
  92. head := map[string]string{
  93. "Content-Type": "image/png",
  94. }
  95. // 将二维码图片作为响应返回给用户
  96. core.WriteBytesResponse(c, nil, qrCode, head)
  97. }
  98. // wechatCallBack
  99. // @Tags 登录
  100. // @BasePath /clodLogistic/app/api/v1
  101. // @Summary 获取微信返回的授权码
  102. // @Success 200 {object} authsrv.LoginRespVo
  103. // @failure 500 {string} codex.ErrSystemSrv
  104. // @Param req body authsrv.LoginReqVo true "登录"
  105. // @Accept application/json
  106. // @Authorization Bearer
  107. // @Router /app/auth/wechatCallback [post]
  108. func (api Api) wechatCallBack(c *gin.Context) {
  109. // 获取微信返回的授权码
  110. code := c.Query("code")
  111. appId := options.OptInstance.Wechat.AppId
  112. appSecret := options.OptInstance.Wechat.AppSecret
  113. // 向微信服务器发送请求,获取access_token和openid
  114. 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))
  115. if err != nil {
  116. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrParamValidate, "error,获取token失败"))
  117. return
  118. }
  119. // 解析响应中的access_token和openid
  120. var tokenData struct {
  121. AccessToken string `json:"access_token"`
  122. ExpiresIn int `json:"expires_in"`
  123. RefreshToken string `json:"refresh_token"`
  124. OpenID string `json:"openid"`
  125. Scope string `json:"scope"`
  126. }
  127. if err1 := json.NewDecoder(tokenResp.Body).Decode(&tokenData); err1 != nil {
  128. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrParamValidate, "error,获取token失败"))
  129. return
  130. }
  131. userInfoURL := fmt.Sprintf("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s", tokenData.AccessToken, tokenData.OpenID)
  132. userInfoResp, err := http.Get(userInfoURL)
  133. defer userInfoResp.Body.Close()
  134. if err != nil {
  135. // 错误处理
  136. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrParamValidate, "获取失败"))
  137. return
  138. }
  139. //------------------------------------
  140. var userData struct {
  141. OpenID string `json:"openid"`
  142. Nickname string `json:"nickname"`
  143. }
  144. if err1 := json.NewDecoder(userInfoResp.Body).Decode(&userData); err1 != nil {
  145. // 错误处理
  146. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrParamValidate, "获取用户信息失败"))
  147. return
  148. }
  149. req := authsrv.LoginReqVo{
  150. LoginType: constant.AccountApplet,
  151. Openid: userData.OpenID,
  152. NickName: userData.Nickname,
  153. }
  154. srv := authsrv.NewAuthService(dao.NewDataStore(global.CommonConnectRepoInst.StoreDB))
  155. res, err := srv.UserLogin(c, req)
  156. if err != nil {
  157. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrSystemSrv, ""))
  158. return
  159. }
  160. core.WriteResponse(c, nil, res)
  161. }
  162. // LoginOut
  163. // @Tags 登录
  164. // @BasePath /clodLogistic/app/api/v1
  165. // @Summary 登出
  166. // @failure 500 {string} codex.ErrSystemSrv
  167. // @Success 200 {string} "success"
  168. // @Accept application/json
  169. // @Authorization Bearer
  170. // @Router /app/auth/loginOut [post]
  171. func (api Api) LoginOut(c *gin.Context) {
  172. srv := authsrv.NewAuthService(dao.NewDataStore(global.CommonConnectRepoInst.StoreDB))
  173. err := srv.LoginOut(c)
  174. if err != nil {
  175. core.WriteErrResponse(c, errors.WithCodeOnce(err, codex.ErrSystemSrv, ""))
  176. return
  177. }
  178. core.WriteResponse(c, nil, "success")
  179. }