368 lines
14 KiB
Go
368 lines
14 KiB
Go
package controllers
|
||
|
||
import (
|
||
"encoding/base64"
|
||
"fmt"
|
||
"net/http"
|
||
"strings"
|
||
|
||
"git.rosy.net.cn/baseapi/platformapi/weixinapi"
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
"git.rosy.net.cn/jx-callback/business/auth2"
|
||
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/dingding"
|
||
_ "git.rosy.net.cn/jx-callback/business/auth2/authprovider/mobile" // 强制导入mobile认证方式
|
||
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/password"
|
||
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
|
||
"git.rosy.net.cn/jx-callback/business/model"
|
||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||
"git.rosy.net.cn/jx-callback/globals"
|
||
beego "github.com/astaxie/beego/adapter"
|
||
)
|
||
|
||
func GetComposedCode(c *beego.Controller, code string) (composedCode string) {
|
||
composedCode = code
|
||
referer := c.Ctx.Request.Referer()
|
||
globals.SugarLogger.Debugf("GetComposedCode referer:%s", referer)
|
||
index := strings.Index(referer, "//")
|
||
if index > 0 {
|
||
list := strings.Split(referer[index+2:], "/")
|
||
if len(list) >= 2 {
|
||
composedCode = weixin.ComposeJsCode(list[1], code)
|
||
}
|
||
}
|
||
return composedCode
|
||
}
|
||
|
||
type Auth2Controller struct {
|
||
beego.Controller
|
||
}
|
||
|
||
// @Title 生成captcha
|
||
// @Description 生成captcha
|
||
// @Param width formData int true "图片宽"
|
||
// @Param height formData int true "图片高"
|
||
// @Param captchaLen formData int false captcha码长度"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /CreateCaptcha [post]
|
||
func (c *Auth2Controller) CreateCaptcha() {
|
||
c.callCreateCaptcha(func(params *tAuth2CreateCaptchaParams) (retVal interface{}, errCode string, err error) {
|
||
retVal, err = auth2.CreateCaptcha(params.Width, params.Height, params.CaptchaLen)
|
||
return retVal, "", err
|
||
})
|
||
}
|
||
|
||
// @Title 发送验证码
|
||
// @Description 发送验证码(captcha码与authToken二者必须至少有一个)
|
||
// @Param captchaID formData string false "captcha码ID"
|
||
// @Param captchaValue formData string false "captcha码值"
|
||
// @Param authToken formData string false "之前的认证信息"
|
||
// @Param authID formData string true "手机号或邮件"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /SendVerifyCode [post]
|
||
func (c *Auth2Controller) SendVerifyCode() {
|
||
c.callSendVerifyCode(func(params *tAuth2SendVerifyCodeParams) (retVal interface{}, errCode string, err error) {
|
||
_, _, err = auth2.SendVerifyCode(params.AuthToken, params.CaptchaID, params.CaptchaValue, params.AuthID)
|
||
// if err == nil && authInfo != nil {
|
||
// user, err2 := dao.GetUserByID(dao.GetDB(), "user_id", authInfo.GetID())
|
||
// if err2 == nil && user.Type&(model.UserTypeBoss|model.UserTypeOperator) != 0 {
|
||
// retVal = code
|
||
// }
|
||
// }
|
||
return retVal, "", err
|
||
})
|
||
}
|
||
|
||
// @Title 登录接口
|
||
// @Description 登录接口(微信与公众号登录不能直接调用此接口)
|
||
// @Param authType formData string true "登录类型,当前支持[localpass:本地账号密码,mobile:手机短信,wxqrcode:微信登录,weixinsns:微信公众号,weixinmini;小程序,wxnative:微信APP,ddstaff:钉钉企业,ddqrcode:钉钉扫码,alipaycode:支付宝小程序]"
|
||
// @Param authSecret formData string true "不同登录类型的登录秘密,如果是localpass登录类型,是md5后的值(空串不要md5)"
|
||
// @Param authID formData string false "登录ID,登录类型为localpass时依赖于authIDType,其它为相应登录类型的id"
|
||
// @Param authIDType formData string false "只有在登录类型为localpass时,才有意义,分别为:userid2:用户名,email,mobile"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /Login [post]
|
||
func (c *Auth2Controller) Login() {
|
||
c.callLogin(func(params *tAuth2LoginParams) (retVal interface{}, errCode string, err error) {
|
||
if params.AuthType == auth2.AuthTypeMobile {
|
||
params.AuthIDType = auth2.UserIDMobile
|
||
} else if params.AuthType == auth2.AuthTypeEmail {
|
||
params.AuthIDType = auth2.UserIDEmail
|
||
}
|
||
if params.AuthType == weixin.AuthTypeMini {
|
||
params.AuthSecret = GetComposedCode(&c.Controller, params.AuthSecret)
|
||
}
|
||
ctx := auth2.NewContext(c.Ctx.ResponseWriter, c.Ctx.Request)
|
||
authInfo, err := auth2.Login(ctx, params.AuthType, params.AuthID, params.AuthIDType, params.AuthSecret)
|
||
// TODO 兼容没有取到authid2的错误
|
||
if err == nil && authInfo.AuthBindInfo != nil {
|
||
if authInfo.AuthBindInfo.AuthID2 == "" {
|
||
authInfo.AuthBindInfo.AuthID2 = authInfo.AuthBindInfo.AuthID
|
||
}
|
||
retVal = authInfo
|
||
}
|
||
return retVal, "", err
|
||
})
|
||
}
|
||
|
||
// @Title 得到自己登录token的信息
|
||
// @Description 得到自己登录token的信息
|
||
// @Param token header string true "认证token"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /GetTokenInfo [get]
|
||
func (c *Auth2Controller) GetTokenInfo() {
|
||
c.callGetTokenInfo(func(params *tAuth2GetTokenInfoParams) (retVal interface{}, errCode string, err error) {
|
||
if true { //auth2.IsV2Token(params.Token) {
|
||
retVal, err = auth2.GetTokenInfo(params.Token)
|
||
} else {
|
||
// retVal, err = auth.GetUserInfo(params.Token)
|
||
}
|
||
if err == model.ErrTokenIsInvalid {
|
||
errCode = model.ErrCodeTokenIsInvalid
|
||
}
|
||
return retVal, errCode, err
|
||
})
|
||
}
|
||
|
||
// @Title 微信扫码认证回调接口
|
||
// @Description 微信扫码认证回调接口,自己不能直接调用
|
||
// @Param code query string true "客户同意后得到的code"
|
||
// @Param block query string true "回调地址"
|
||
// @Param state query string false "微信回调的登录状态"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /WeixinOAuth2 [get]
|
||
func (c *Auth2Controller) WeixinOAuth2() {
|
||
var (
|
||
redirectURL string
|
||
callResult *CallResult
|
||
)
|
||
c.callWeixinOAuth2(func(params *tAuth2WeixinOAuth2Params) (retVal interface{}, errCode string, err error) {
|
||
ctx := auth2.NewContext(c.Ctx.ResponseWriter, c.Ctx.Request)
|
||
authInfo, err := auth2.Login(ctx, weixin.AuthTypeWeixin, params.State, "", params.Code)
|
||
if err == nil {
|
||
callResult = &CallResult{
|
||
Code: model.ErrCodeSuccess,
|
||
Data: string(utils.MustMarshal(authInfo)),
|
||
}
|
||
} else {
|
||
callResult = &CallResult{
|
||
Code: model.ErrCodeGeneralFailed,
|
||
Desc: err.Error(),
|
||
}
|
||
}
|
||
redirectURL = fmt.Sprintf("%s?info=%s", params.Block, base64.StdEncoding.EncodeToString(utils.MustMarshal(callResult)))
|
||
return retVal, model.ErrorCodeIgnore, err
|
||
})
|
||
globals.SugarLogger.Debugf("WeixinOAuth2, callResult:%s, redirectURL:%s", utils.Format4Output(callResult, true), redirectURL)
|
||
c.Redirect(redirectURL, http.StatusTemporaryRedirect)
|
||
}
|
||
|
||
// @Title 微信公众号认证回调接口
|
||
// @Description 微信公众号认证回调接口,自己不能直接调用
|
||
// @Param code query string true "客户同意后得到的code"
|
||
// @Param block query string true "回调地址"
|
||
// @Param state query string false "微信回调的登录状态"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /WeixinMPOAuth2 [get]
|
||
func (c *Auth2Controller) WeixinMPOAuth2() {
|
||
var (
|
||
redirectURL string
|
||
callResult *CallResult
|
||
)
|
||
c.callWeixinMPOAuth2(func(params *tAuth2WeixinMPOAuth2Params) (retVal interface{}, errCode string, err error) {
|
||
ctx := auth2.NewContext(c.Ctx.ResponseWriter, c.Ctx.Request)
|
||
authInfo, err := auth2.Login(ctx, weixin.AuthTypeMP, params.State, "", params.Code)
|
||
if err == nil {
|
||
callResult = &CallResult{
|
||
Code: model.ErrCodeSuccess,
|
||
Data: string(utils.MustMarshal(authInfo)),
|
||
}
|
||
} else {
|
||
callResult = &CallResult{
|
||
Code: model.ErrCodeGeneralFailed,
|
||
Desc: err.Error(),
|
||
}
|
||
}
|
||
redirectURL = fmt.Sprintf("%s?info=%s", params.Block, base64.StdEncoding.EncodeToString(utils.MustMarshal(callResult)))
|
||
return retVal, model.ErrorCodeIgnore, err
|
||
})
|
||
globals.SugarLogger.Debugf("WeixinMPOAuth2, callResult:%s, redirectURL:%s", utils.Format4Output(callResult, true), redirectURL)
|
||
c.Redirect(redirectURL, http.StatusTemporaryRedirect)
|
||
}
|
||
|
||
// @Title 钉钉认证回调接口
|
||
// @Description 钉钉认证回调接口,自己不能直接调用
|
||
// @Param code query string true "客户同意后得到的code"
|
||
// @Param block query string false "回调地址"
|
||
// @Param state query string false "微信回调的登录状态"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /DingDingOAuth2 [get]
|
||
func (c *Auth2Controller) DingDingOAuth2() {
|
||
var (
|
||
redirectURL string
|
||
callResult *CallResult
|
||
)
|
||
c.callDingDingOAuth2(func(params *tAuth2DingDingOAuth2Params) (retVal interface{}, errCode string, err error) {
|
||
if params.Block == "" {
|
||
params.Block = params.State
|
||
params.State = ""
|
||
}
|
||
ctx := auth2.NewContext(c.Ctx.ResponseWriter, c.Ctx.Request)
|
||
authInfo, err := auth2.Login(ctx, dingding.AuthTypeQRCode, params.State, "", params.Code)
|
||
if err == nil {
|
||
callResult = &CallResult{
|
||
Code: model.ErrCodeSuccess,
|
||
Data: string(utils.MustMarshal(authInfo)),
|
||
}
|
||
} else {
|
||
callResult = &CallResult{
|
||
Code: model.ErrCodeGeneralFailed,
|
||
Desc: err.Error(),
|
||
}
|
||
}
|
||
if params.Block != "" {
|
||
redirectURL = fmt.Sprintf("%s?info=%s", params.Block, base64.StdEncoding.EncodeToString(utils.MustMarshal(callResult)))
|
||
}
|
||
return retVal, model.ErrorCodeIgnore, err
|
||
})
|
||
globals.SugarLogger.Debugf("DingDingOAuth2, callResult:%s, redirectURL:%s", utils.Format4Output(callResult, true), redirectURL)
|
||
if redirectURL != "" {
|
||
c.Redirect(redirectURL, http.StatusTemporaryRedirect)
|
||
}
|
||
}
|
||
|
||
// @Title 登出接口
|
||
// @Description 登出接口(此接口兼容V1的TOKEN)
|
||
// @Param token header string true "认证token"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /Logout [delete]
|
||
func (c *Auth2Controller) Logout() {
|
||
c.callLogout(func(params *tAuth2LogoutParams) (retVal interface{}, errCode string, err error) {
|
||
if authInfo, ok := params.Ctx.GetLoginInfo().(*auth2.AuthInfo); ok {
|
||
err = auth2.Logout(authInfo)
|
||
} else {
|
||
// err = auth.Logout(params.Token)
|
||
}
|
||
return nil, "", err
|
||
})
|
||
}
|
||
|
||
// @Title 绑定认证方式
|
||
// @Description 绑定认证方式
|
||
// @Param token header string true "认证token"
|
||
// @Param authToken formData string true "之前通过login得到的新认证TOKEN"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /AddAuthBind [post]
|
||
func (c *Auth2Controller) AddAuthBind() {
|
||
c.callAddAuthBind(func(params *tAuth2AddAuthBindParams) (retVal interface{}, errCode string, err error) {
|
||
authInfo, err2 := params.Ctx.GetV2AuthInfo()
|
||
if err := err2; err == nil {
|
||
newAuthInfo, err2 := auth2.GetTokenInfo(params.AuthToken)
|
||
if err = err2; err == nil {
|
||
err = auth2.AddAuthBind(authInfo, newAuthInfo)
|
||
}
|
||
}
|
||
return retVal, "", err
|
||
})
|
||
}
|
||
|
||
// @Title 删除认证方式
|
||
// @Description 删除认证方式
|
||
// @Param token header string true "认证token"
|
||
// @Param authType query string true "登录类型,参见Login的描述"
|
||
// @Param authTypeID query string false "登录类型标识"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /RemoveAuthBind [delete]
|
||
func (c *Auth2Controller) RemoveAuthBind() {
|
||
c.callRemoveAuthBind(func(params *tAuth2RemoveAuthBindParams) (retVal interface{}, errCode string, err error) {
|
||
authInfo, err2 := params.Ctx.GetV2AuthInfo()
|
||
if err = err2; err == nil {
|
||
err = auth2.UnbindAuth(authInfo.GetID(), params.AuthType, params.AuthTypeID, params.Ctx.GetUserName())
|
||
}
|
||
return retVal, "", err
|
||
})
|
||
}
|
||
|
||
// @Title 修改(或初始化)密码
|
||
// @Description 修改(或初始化)密码
|
||
// @Param token header string true "认证token"
|
||
// @Param oldPwd query string false "原密码md5,如果是重置或新设,为空"
|
||
// @Param newPwd query string true "新密码md5"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /ChangePassword [put]
|
||
func (c *Auth2Controller) ChangePassword() {
|
||
c.callChangePassword(func(params *tAuth2ChangePasswordParams) (retVal interface{}, errCode string, err error) {
|
||
authInfo, err := params.Ctx.GetV2AuthInfo()
|
||
if err == nil {
|
||
err = password.AutherObj.ChangePassword(authInfo.GetID(), params.Ctx.GetUserName(), params.OldPwd, params.NewPwd)
|
||
}
|
||
return retVal, "", err
|
||
})
|
||
}
|
||
|
||
// @Title 清除除参数token以外的这个人的token
|
||
// @Description 清除除参数token以外的这个人的token
|
||
// @Param token header string true "认证token"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /DeletedTokenInfoWithoutParam [put]
|
||
func (c *Auth2Controller) DeletedTokenInfoWithoutParam() {
|
||
c.callDeletedTokenInfoWithoutParam(func(params *tAuth2DeletedTokenInfoWithoutParamParams) (retVal interface{}, errCode string, err error) {
|
||
newAuthInfo, err2 := auth2.GetTokenInfo(params.Token)
|
||
if err = err2; err == nil {
|
||
err = auth2.DeletedTokenInfoWithoutParam(newAuthInfo)
|
||
}
|
||
return retVal, "", err
|
||
})
|
||
}
|
||
|
||
type UserInfoWithWeixin struct {
|
||
Mobile string `json:"mobile"`
|
||
IsExist bool `json:"isExist"`
|
||
}
|
||
|
||
// @Title 根据小程序jsCode查询用户信息
|
||
// @Description 根据小程序jsCode查询用户信息
|
||
// @Param token header string false "认证token"
|
||
// @Param data formData string true "加密数据"
|
||
// @Param iv formData string true "iv"
|
||
// @Param jsCode formData string false "小程序jsCode"
|
||
// @Success 200 {object} controllers.CallResult
|
||
// @Failure 200 {object} controllers.CallResult
|
||
// @router /GetUserByMiniInfo [post]
|
||
func (c *Auth2Controller) GetUserByMiniInfo() {
|
||
c.callGetUserByMiniInfo(func(params *tAuth2GetUserByMiniInfoParams) (retVal interface{}, errCode string, err error) {
|
||
authInfo := &auth2.AuthInfo{}
|
||
if err == nil {
|
||
decryptedDataBase64, err2 := weixin.AutherObjMini.DecryptData(authInfo, GetComposedCode(&c.Controller, params.JsCode), params.Data, params.Iv)
|
||
if err = err2; err == nil {
|
||
var userInfo *weixinapi.MiniUserInfo
|
||
if err = utils.UnmarshalUseNumber([]byte(decryptedDataBase64), &userInfo); err == nil {
|
||
result := &UserInfoWithWeixin{}
|
||
result.Mobile = userInfo.PhoneNumber
|
||
if userInfo.PhoneNumber != "" {
|
||
if user, err := dao.GetUserByID(dao.GetDB(), "mobile", userInfo.PhoneNumber); err == nil {
|
||
if user != nil {
|
||
result.IsExist = true
|
||
} else {
|
||
result.IsExist = false
|
||
}
|
||
}
|
||
}
|
||
retVal = result
|
||
}
|
||
}
|
||
}
|
||
return retVal, "", err
|
||
})
|
||
}
|