mirror of
				https://github.com/genxium/DelayNoMore
				synced 2025-10-31 19:37:00 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			717 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			717 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package v1
 | |
| 
 | |
| import (
 | |
| 	"battle_srv/api"
 | |
| 	. "battle_srv/common"
 | |
| 	"battle_srv/common/utils"
 | |
| 	"battle_srv/models"
 | |
| 	. "battle_srv/protos"
 | |
| 	"battle_srv/storage"
 | |
| 	"bytes"
 | |
| 	"crypto/sha256"
 | |
| 	"encoding/hex"
 | |
| 	"encoding/json"
 | |
| 	"github.com/gin-gonic/gin"
 | |
| 	"github.com/gin-gonic/gin/binding"
 | |
| 	"go.uber.org/zap"
 | |
| 	"io/ioutil"
 | |
| 	"net/http"
 | |
| 	"strconv"
 | |
| 
 | |
| 	. "dnmshared"
 | |
| )
 | |
| 
 | |
| var Player = playerController{}
 | |
| 
 | |
| type playerController struct {
 | |
| }
 | |
| 
 | |
| type smsCaptchaReq struct {
 | |
| 	Num         string `json:"phoneNum,omitempty" form:"phoneNum"`
 | |
| 	CountryCode string `json:"phoneCountryCode,omitempty" form:"phoneCountryCode"`
 | |
| 	Captcha     string `json:"smsLoginCaptcha,omitempty" form:"smsLoginCaptcha"`
 | |
| }
 | |
| 
 | |
| func (req *smsCaptchaReq) extAuthID() string {
 | |
| 	return req.CountryCode + req.Num
 | |
| }
 | |
| func (req *smsCaptchaReq) redisKey() string {
 | |
| 	return "/cuisine/sms/captcha/" + req.extAuthID()
 | |
| }
 | |
| 
 | |
| type wechatShareConfigReq struct {
 | |
| 	Url string `form:"url"`
 | |
| }
 | |
| 
 | |
| func (p *playerController) GetWechatShareConfig(c *gin.Context) {
 | |
| 	var req wechatShareConfigReq
 | |
| 	err := c.ShouldBindWith(&req, binding.FormPost)
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil || req.Url == "" {
 | |
| 		c.Set(api.RET, Constants.RetCode.InvalidRequestParam)
 | |
| 		return
 | |
| 	}
 | |
| 	config, err := utils.WechatIns.GetJsConfig(req.Url)
 | |
| 	if err != nil {
 | |
| 		Logger.Info("err", zap.Any("", err))
 | |
| 		c.Set(api.RET, Constants.RetCode.WechatServerError)
 | |
| 		return
 | |
| 	}
 | |
| 	resp := struct {
 | |
| 		Ret    int             `json:"ret"`
 | |
| 		Config *utils.JsConfig `json:"jsConfig"`
 | |
| 	}{Constants.RetCode.Ok, config}
 | |
| 	c.JSON(http.StatusOK, resp)
 | |
| }
 | |
| 
 | |
| func (p *playerController) SMSCaptchaGet(c *gin.Context) {
 | |
| 	var req smsCaptchaReq
 | |
| 	err := c.ShouldBindQuery(&req)
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil || req.Num == "" || req.CountryCode == "" {
 | |
| 		c.Set(api.RET, Constants.RetCode.InvalidRequestParam)
 | |
| 		return
 | |
| 	}
 | |
| 	// Composite a key to access against Redis-server.
 | |
| 	redisKey := req.redisKey()
 | |
| 	ttl, err := storage.RedisManagerIns.TTL(redisKey).Result()
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil {
 | |
| 		c.Set(api.RET, Constants.RetCode.UnknownError)
 | |
| 		return
 | |
| 	}
 | |
| 	if ttl >= ConstVals.Player.CaptchaMaxTTL {
 | |
| 		Logger.Info("There's an existing SmsCaptcha record in Redis-server: ", zap.String("key", redisKey), zap.Duration("ttl", ttl))
 | |
| 		c.Set(api.RET, Constants.RetCode.SmsCaptchaRequestedTooFrequently)
 | |
| 		return
 | |
| 	}
 | |
| 	Logger.Info("A new SmsCaptcha record is needed for: ", zap.String("key", redisKey))
 | |
| 	pass := false
 | |
| 	var succRet int
 | |
| 	if Conf.General.ServerEnv == SERVER_ENV_TEST {
 | |
| 		player, err := models.GetPlayerByName(req.Num)
 | |
| 		if nil == err && nil != player {
 | |
| 			pass = true
 | |
| 			succRet = Constants.RetCode.IsTestAcc
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if !pass {
 | |
| 		player, err := models.GetPlayerByName(req.Num)
 | |
| 		if nil == err && nil != player {
 | |
| 			pass = true
 | |
| 			succRet = Constants.RetCode.IsBotAcc
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if !pass {
 | |
| 		if RE_PHONE_NUM.MatchString(req.Num) {
 | |
| 			succRet = Constants.RetCode.Ok
 | |
| 			pass = true
 | |
| 		}
 | |
| 		if req.CountryCode == "86" {
 | |
| 			if RE_CHINA_PHONE_NUM.MatchString(req.Num) {
 | |
| 				succRet = Constants.RetCode.Ok
 | |
| 				pass = true
 | |
| 			} else {
 | |
| 				succRet = Constants.RetCode.InvalidRequestParam
 | |
| 				pass = false
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	if !pass {
 | |
| 		c.Set(api.RET, Constants.RetCode.InvalidRequestParam)
 | |
| 		return
 | |
| 	}
 | |
| 	resp := struct {
 | |
| 		Ret int `json:"ret"`
 | |
| 		smsCaptchaReq
 | |
| 		GetSmsCaptchaRespErrorCode int `json:"getSmsCaptchaRespErrorCode"`
 | |
| 	}{Ret: succRet}
 | |
| 	var captcha string
 | |
| 	if ttl >= 0 {
 | |
| 		storage.RedisManagerIns.Expire(redisKey, ConstVals.Player.CaptchaExpire)
 | |
| 		captcha = storage.RedisManagerIns.Get(redisKey).Val()
 | |
| 		if ttl >= ConstVals.Player.CaptchaExpire/4 {
 | |
| 			if succRet == Constants.RetCode.Ok {
 | |
| 				getSmsCaptchaRespErrorCode := sendSMSViaVendor(req.Num, req.CountryCode, captcha)
 | |
| 				if getSmsCaptchaRespErrorCode != 0 {
 | |
| 					resp.Ret = Constants.RetCode.GetSmsCaptchaRespErrorCode
 | |
| 					resp.GetSmsCaptchaRespErrorCode = getSmsCaptchaRespErrorCode
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		Logger.Info("Extended ttl of existing SMSCaptcha record in Redis:", zap.String("key", redisKey), zap.String("captcha", captcha))
 | |
| 	} else {
 | |
| 		captcha = strconv.Itoa(utils.Rand.Number(1000, 9999))
 | |
| 		if succRet == Constants.RetCode.Ok {
 | |
| 			getSmsCaptchaRespErrorCode := sendSMSViaVendor(req.Num, req.CountryCode, captcha)
 | |
| 			if getSmsCaptchaRespErrorCode != 0 {
 | |
| 				resp.Ret = Constants.RetCode.GetSmsCaptchaRespErrorCode
 | |
| 				resp.GetSmsCaptchaRespErrorCode = getSmsCaptchaRespErrorCode
 | |
| 			}
 | |
| 		}
 | |
| 		storage.RedisManagerIns.Set(redisKey, captcha, ConstVals.Player.CaptchaExpire)
 | |
| 		Logger.Info("Generated new captcha", zap.String("key", redisKey), zap.String("captcha", captcha))
 | |
| 	}
 | |
| 	if succRet == Constants.RetCode.IsTestAcc {
 | |
| 		resp.Captcha = captcha
 | |
| 	}
 | |
| 	if succRet == Constants.RetCode.IsBotAcc {
 | |
| 		resp.Captcha = captcha
 | |
| 	}
 | |
| 	c.JSON(http.StatusOK, resp)
 | |
| }
 | |
| 
 | |
| func (p *playerController) SMSCaptchaLogin(c *gin.Context) {
 | |
| 	var req smsCaptchaReq
 | |
| 	err := c.ShouldBindWith(&req, binding.FormPost)
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil || req.Num == "" || req.CountryCode == "" || req.Captcha == "" {
 | |
| 		c.Set(api.RET, Constants.RetCode.InvalidRequestParam)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	redisKey := req.redisKey()
 | |
| 	captcha := storage.RedisManagerIns.Get(redisKey).Val()
 | |
| 	Logger.Info("Comparing captchas", zap.String("key", redisKey), zap.String("whats-in-redis", captcha), zap.String("whats-from-req", req.Captcha))
 | |
| 	if captcha != req.Captcha {
 | |
| 		c.Set(api.RET, Constants.RetCode.SmsCaptchaNotMatch)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	player, err := p.maybeCreateNewPlayer(req)
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil {
 | |
| 		c.Set(api.RET, Constants.RetCode.MysqlError)
 | |
| 		return
 | |
| 	}
 | |
| 	now := utils.UnixtimeMilli()
 | |
| 	token := utils.TokenGenerator(32)
 | |
| 	expiresAt := now + 1000*int64(Constants.Player.IntAuthTokenTTLSeconds)
 | |
| 	playerLogin := models.PlayerLogin{
 | |
| 		CreatedAt:    now,
 | |
| 		FromPublicIP: models.NewNullString(c.ClientIP()),
 | |
| 		IntAuthToken: token,
 | |
| 		PlayerID:     int(player.Id),
 | |
| 		DisplayName:  models.NewNullString(player.DisplayName),
 | |
| 		UpdatedAt:    now,
 | |
| 	}
 | |
| 	err = playerLogin.Insert()
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil {
 | |
| 		c.Set(api.RET, Constants.RetCode.MysqlError)
 | |
| 		return
 | |
| 	}
 | |
| 	storage.RedisManagerIns.Del(redisKey)
 | |
| 	resp := struct {
 | |
| 		Ret         int    `json:"ret"`
 | |
| 		Token       string `json:"intAuthToken"`
 | |
| 		ExpiresAt   int64  `json:"expiresAt"`
 | |
| 		PlayerID    int    `json:"playerId"`
 | |
| 		DisplayName string `json:"displayName"`
 | |
| 		Name        string `json:"name"`
 | |
| 	}{Constants.RetCode.Ok, token, expiresAt, int(player.Id), player.DisplayName, player.Name}
 | |
| 
 | |
| 	c.JSON(http.StatusOK, resp)
 | |
| }
 | |
| 
 | |
| type wechatLogin struct {
 | |
| 	Authcode string `form:"code"`
 | |
| }
 | |
| 
 | |
| func (p *playerController) WechatLogin(c *gin.Context) {
 | |
| 	var req wechatLogin
 | |
| 	err := c.ShouldBindWith(&req, binding.FormPost)
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil || req.Authcode == "" {
 | |
| 		c.Set(api.RET, Constants.RetCode.InvalidRequestParam)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	baseInfo, err := utils.WechatIns.GetOauth2Basic(req.Authcode)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		Logger.Info("err", zap.Any("", err))
 | |
| 		c.Set(api.RET, Constants.RetCode.WechatServerError)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	userInfo, err := utils.WechatIns.GetMoreInfo(baseInfo.AccessToken, baseInfo.OpenID)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		Logger.Info("err", zap.Any("", err))
 | |
| 		c.Set(api.RET, Constants.RetCode.WechatServerError)
 | |
| 		return
 | |
| 	}
 | |
| 	userInfo.OpenID = baseInfo.OpenID
 | |
| 
 | |
| 	player, err := p.maybeCreatePlayerWechatAuthBinding(userInfo)
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil {
 | |
| 		c.Set(api.RET, Constants.RetCode.MysqlError)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	now := utils.UnixtimeMilli()
 | |
| 	token := utils.TokenGenerator(32)
 | |
| 	expiresAt := now + 1000*int64(Constants.Player.IntAuthTokenTTLSeconds)
 | |
| 	playerLogin := models.PlayerLogin{
 | |
| 		CreatedAt:    now,
 | |
| 		FromPublicIP: models.NewNullString(c.ClientIP()),
 | |
| 		IntAuthToken: token,
 | |
| 		PlayerID:     int(player.Id),
 | |
| 		DisplayName:  models.NewNullString(player.DisplayName),
 | |
| 		UpdatedAt:    now,
 | |
| 		Avatar:       userInfo.HeadImgURL,
 | |
| 	}
 | |
| 	err = playerLogin.Insert()
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil {
 | |
| 		c.Set(api.RET, Constants.RetCode.MysqlError)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	resp := struct {
 | |
| 		Ret         int               `json:"ret"`
 | |
| 		Token       string            `json:"intAuthToken"`
 | |
| 		ExpiresAt   int64             `json:"expiresAt"`
 | |
| 		PlayerID    int               `json:"playerId"`
 | |
| 		DisplayName models.NullString `json:"displayName"`
 | |
| 		Avatar      string            `json:"avatar"`
 | |
| 	}{
 | |
| 		Constants.RetCode.Ok,
 | |
| 		token, expiresAt,
 | |
| 		playerLogin.PlayerID,
 | |
| 		playerLogin.DisplayName,
 | |
| 		userInfo.HeadImgURL,
 | |
| 	}
 | |
| 	c.JSON(http.StatusOK, resp)
 | |
| }
 | |
| 
 | |
| type wechatGameLogin struct {
 | |
| 	Authcode  string `form:"code"`
 | |
| 	AvatarUrl string `form:"avatarUrl"`
 | |
| 	NickName  string `form:"nickName"`
 | |
| }
 | |
| 
 | |
| func (p *playerController) WechatGameLogin(c *gin.Context) {
 | |
| 	var req wechatGameLogin
 | |
| 	err := c.ShouldBindWith(&req, binding.FormPost)
 | |
| 	if nil != err {
 | |
| 		Logger.Error("WechatGameLogin got an invalid request param error", zap.Error(err))
 | |
| 		c.Set(api.RET, Constants.RetCode.InvalidRequestParam)
 | |
| 		return
 | |
| 	}
 | |
| 	if "" == req.Authcode {
 | |
| 		Logger.Warn("WechatGameLogin got an invalid request param", zap.Any("req", req))
 | |
| 		c.Set(api.RET, Constants.RetCode.InvalidRequestParam)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	baseInfo, err := utils.WechatGameIns.GetOauth2Basic(req.Authcode)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		Logger.Info("err", zap.Any("", err))
 | |
| 		c.Set(api.RET, Constants.RetCode.WechatServerError)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	Logger.Info("baseInfo", zap.Any(":", baseInfo))
 | |
| 	//crate new userInfo from client userInfo
 | |
| 	userInfo := utils.UserInfo{
 | |
| 		Nickname:   req.NickName,
 | |
| 		HeadImgURL: req.AvatarUrl,
 | |
| 	}
 | |
| 
 | |
| 	if err != nil {
 | |
| 		Logger.Info("err", zap.Any("", err))
 | |
| 		c.Set(api.RET, Constants.RetCode.WechatServerError)
 | |
| 		return
 | |
| 	}
 | |
| 	userInfo.OpenID = baseInfo.OpenID
 | |
| 
 | |
| 	player, err := p.maybeCreatePlayerWechatGameAuthBinding(userInfo)
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil {
 | |
| 		c.Set(api.RET, Constants.RetCode.MysqlError)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	now := utils.UnixtimeMilli()
 | |
| 	token := utils.TokenGenerator(32)
 | |
| 	expiresAt := now + 1000*int64(Constants.Player.IntAuthTokenTTLSeconds)
 | |
| 	playerLogin := models.PlayerLogin{
 | |
| 		CreatedAt:    now,
 | |
| 		FromPublicIP: models.NewNullString(c.ClientIP()),
 | |
| 		IntAuthToken: token,
 | |
| 		PlayerID:     int(player.Id),
 | |
| 		DisplayName:  models.NewNullString(player.DisplayName),
 | |
| 		UpdatedAt:    now,
 | |
| 		Avatar:       userInfo.HeadImgURL,
 | |
| 	}
 | |
| 	err = playerLogin.Insert()
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil {
 | |
| 		c.Set(api.RET, Constants.RetCode.MysqlError)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	resp := struct {
 | |
| 		Ret         int               `json:"ret"`
 | |
| 		Token       string            `json:"intAuthToken"`
 | |
| 		ExpiresAt   int64             `json:"expiresAt"`
 | |
| 		PlayerID    int               `json:"playerId"`
 | |
| 		DisplayName models.NullString `json:"displayName"`
 | |
| 		Avatar      string            `json:"avatar"`
 | |
| 	}{
 | |
| 		Constants.RetCode.Ok,
 | |
| 		token, expiresAt,
 | |
| 		playerLogin.PlayerID,
 | |
| 		playerLogin.DisplayName,
 | |
| 		userInfo.HeadImgURL,
 | |
| 	}
 | |
| 	c.JSON(http.StatusOK, resp)
 | |
| }
 | |
| 
 | |
| func (p *playerController) IntAuthTokenLogin(c *gin.Context) {
 | |
| 	token := p.getIntAuthToken(c)
 | |
| 	if "" == token {
 | |
| 		return
 | |
| 	}
 | |
| 	playerLogin, err := models.GetPlayerLoginByToken(token)
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil || playerLogin == nil {
 | |
| 		c.Set(api.RET, Constants.RetCode.InvalidToken)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	player, err := models.GetPlayerById(playerLogin.PlayerID)
 | |
| 	if err != nil {
 | |
| 		Logger.Error("Get player by id in IntAuthTokenLogin function error: ", zap.Error(err))
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	expiresAt := playerLogin.UpdatedAt + 1000*int64(Constants.Player.IntAuthTokenTTLSeconds)
 | |
| 	resp := struct {
 | |
| 		Ret         int    `json:"ret"`
 | |
| 		Token       string `json:"intAuthToken"`
 | |
| 		ExpiresAt   int64  `json:"expiresAt"`
 | |
| 		PlayerID    int    `json:"playerId"`
 | |
| 		DisplayName string `json:"displayName"`
 | |
| 		Avatar      string `json:"avatar"`
 | |
| 		Name        string `json:"name"`
 | |
| 	}{Constants.RetCode.Ok, token, expiresAt,
 | |
| 		playerLogin.PlayerID, player.DisplayName,
 | |
| 		playerLogin.Avatar, player.Name,
 | |
| 	}
 | |
| 	c.JSON(http.StatusOK, resp)
 | |
| }
 | |
| 
 | |
| func (p *playerController) IntAuthTokenLogout(c *gin.Context) {
 | |
| 	token := p.getIntAuthToken(c)
 | |
| 	if "" == token {
 | |
| 		return
 | |
| 	}
 | |
| 	err := models.DelPlayerLoginByToken(token)
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil {
 | |
| 		c.Set(api.RET, Constants.RetCode.UnknownError)
 | |
| 		return
 | |
| 	}
 | |
| 	c.Set(api.RET, Constants.RetCode.Ok)
 | |
| }
 | |
| 
 | |
| func (p *playerController) FetchProfile(c *gin.Context) {
 | |
| 	targetPlayerId := c.GetInt(api.TARGET_PLAYER_ID)
 | |
| 	wallet, err := models.GetPlayerWalletById(targetPlayerId)
 | |
| 	if err != nil {
 | |
| 		api.CErr(c, err)
 | |
| 		c.Set(api.RET, Constants.RetCode.MysqlError)
 | |
| 		return
 | |
| 	}
 | |
| 	player, err := models.GetPlayerById(targetPlayerId)
 | |
| 	if err != nil {
 | |
| 		api.CErr(c, err)
 | |
| 		c.Set(api.RET, Constants.RetCode.MysqlError)
 | |
| 		return
 | |
| 	}
 | |
| 	if wallet == nil || player == nil {
 | |
| 		c.Set(api.RET, Constants.RetCode.InvalidRequestParam)
 | |
| 		return
 | |
| 	}
 | |
| 	resp := struct {
 | |
| 		Ret           int                  `json:"ret"`
 | |
| 		TutorialStage int                  `json:"tutorialStage"`
 | |
| 		Wallet        *models.PlayerWallet `json:"wallet"`
 | |
| 	}{Constants.RetCode.Ok, player.TutorialStage, wallet}
 | |
| 	c.JSON(http.StatusOK, resp)
 | |
| }
 | |
| 
 | |
| func (p *playerController) TokenAuth(c *gin.Context) {
 | |
| 	var req struct {
 | |
| 		Token          string `form:"intAuthToken"`
 | |
| 		TargetPlayerId int    `form:"targetPlayerId"`
 | |
| 	}
 | |
| 	err := c.ShouldBindWith(&req, binding.FormPost)
 | |
| 	if err == nil {
 | |
| 		playerLogin, err := models.GetPlayerLoginByToken(req.Token)
 | |
| 		api.CErr(c, err)
 | |
| 		if err == nil && playerLogin != nil {
 | |
| 			c.Set(api.PLAYER_ID, playerLogin.PlayerID)
 | |
| 			c.Set(api.TARGET_PLAYER_ID, req.TargetPlayerId)
 | |
| 			c.Next()
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 	Logger.Debug("TokenAuth Failed", zap.String("token", req.Token))
 | |
| 	c.Set(api.RET, Constants.RetCode.InvalidToken)
 | |
| 	c.Abort()
 | |
| }
 | |
| 
 | |
| func (p *playerController) maybeCreateNewPlayer(req smsCaptchaReq) (*models.Player, error) {
 | |
| 	extAuthID := req.extAuthID()
 | |
| 	if Conf.General.ServerEnv == SERVER_ENV_TEST {
 | |
| 		player, err := models.GetPlayerByName(req.Num)
 | |
| 		if err != nil {
 | |
| 			Logger.Error("Seeking test env player error:", zap.Error(err))
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if player != nil {
 | |
| 			Logger.Info("Got a test env player:", zap.Any("phonenum", req.Num), zap.Any("playerId", player.Id))
 | |
| 			return player, nil
 | |
| 		}
 | |
| 	} else {
 | |
| 		botPlayer, err := models.GetPlayerByName(req.Num)
 | |
| 		if err != nil {
 | |
| 			Logger.Error("Seeking bot player error:", zap.Error(err))
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if botPlayer != nil {
 | |
| 			Logger.Info("Got a bot player:", zap.Any("phonenum", req.Num), zap.Any("playerId", botPlayer.Id))
 | |
| 			return botPlayer, nil
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	bind, err := models.GetPlayerAuthBinding(Constants.AuthChannel.Sms, extAuthID)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if bind != nil {
 | |
| 		player, err := models.GetPlayerById(bind.PlayerID)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if player != nil {
 | |
| 			return player, nil
 | |
| 		}
 | |
| 	}
 | |
| 	now := utils.UnixtimeMilli()
 | |
| 	player := models.Player{
 | |
| 		CreatedAt: now,
 | |
| 		UpdatedAt: now,
 | |
| 	}
 | |
| 	return p.createNewPlayer(player, extAuthID, int(Constants.AuthChannel.Sms))
 | |
| 
 | |
| }
 | |
| 
 | |
| func (p *playerController) maybeCreatePlayerWechatAuthBinding(userInfo utils.UserInfo) (*models.Player, error) {
 | |
| 	bind, err := models.GetPlayerAuthBinding(Constants.AuthChannel.Wechat, userInfo.OpenID)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if bind != nil {
 | |
| 		player, err := models.GetPlayerById(bind.PlayerID)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if player != nil {
 | |
| 			updateInfo := models.Player{
 | |
| 				PlayerDownsync: PlayerDownsync{
 | |
| 					Avatar:      userInfo.HeadImgURL,
 | |
| 					DisplayName: userInfo.Nickname,
 | |
| 				},
 | |
| 			}
 | |
| 			tx := storage.MySQLManagerIns.MustBegin()
 | |
| 			defer tx.Rollback()
 | |
| 			ok, err := models.Update(tx, player.Id, &updateInfo)
 | |
| 			if err != nil && ok != true {
 | |
| 				return nil, err
 | |
| 			} else {
 | |
| 				tx.Commit()
 | |
| 			}
 | |
| 			return player, nil
 | |
| 		}
 | |
| 	}
 | |
| 	now := utils.UnixtimeMilli()
 | |
| 	player := models.Player{
 | |
| 		PlayerDownsync: PlayerDownsync{
 | |
| 			DisplayName: userInfo.Nickname,
 | |
| 			Avatar:      userInfo.HeadImgURL,
 | |
| 		},
 | |
| 		CreatedAt: now,
 | |
| 		UpdatedAt: now,
 | |
| 	}
 | |
| 	return p.createNewPlayer(player, userInfo.OpenID, int(Constants.AuthChannel.Wechat))
 | |
| }
 | |
| 
 | |
| func (p *playerController) maybeCreatePlayerWechatGameAuthBinding(userInfo utils.UserInfo) (*models.Player, error) {
 | |
| 	bind, err := models.GetPlayerAuthBinding(Constants.AuthChannel.WechatGame, userInfo.OpenID)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if bind != nil {
 | |
| 		player, err := models.GetPlayerById(bind.PlayerID)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if player != nil {
 | |
| 			updateInfo := models.Player{
 | |
| 				PlayerDownsync: PlayerDownsync{
 | |
| 					Avatar:      userInfo.HeadImgURL,
 | |
| 					DisplayName: userInfo.Nickname,
 | |
| 				},
 | |
| 			}
 | |
| 			tx := storage.MySQLManagerIns.MustBegin()
 | |
| 			defer tx.Rollback()
 | |
| 			ok, err := models.Update(tx, player.Id, &updateInfo)
 | |
| 			if err != nil && ok != true {
 | |
| 				return nil, err
 | |
| 			} else {
 | |
| 				tx.Commit()
 | |
| 			}
 | |
| 			return player, nil
 | |
| 		}
 | |
| 	}
 | |
| 	now := utils.UnixtimeMilli()
 | |
| 	player := models.Player{
 | |
| 		PlayerDownsync: PlayerDownsync{
 | |
| 			DisplayName: userInfo.Nickname,
 | |
| 			Avatar:      userInfo.HeadImgURL,
 | |
| 		},
 | |
| 		CreatedAt: now,
 | |
| 		UpdatedAt: now,
 | |
| 	}
 | |
| 	return p.createNewPlayer(player, userInfo.OpenID, int(Constants.AuthChannel.WechatGame))
 | |
| }
 | |
| 
 | |
| func (p *playerController) createNewPlayer(player models.Player, extAuthID string, channel int) (*models.Player, error) {
 | |
| 	Logger.Debug("createNewPlayer", zap.String("extAuthID", extAuthID))
 | |
| 	now := utils.UnixtimeMilli()
 | |
| 	tx := storage.MySQLManagerIns.MustBegin()
 | |
| 	defer tx.Rollback()
 | |
| 	err := player.Insert(tx)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	playerAuthBinding := models.PlayerAuthBinding{
 | |
| 		CreatedAt: now,
 | |
| 		UpdatedAt: now,
 | |
| 		Channel:   channel,
 | |
| 		ExtAuthID: extAuthID,
 | |
| 		PlayerID:  int(player.Id),
 | |
| 	}
 | |
| 	err = playerAuthBinding.Insert(tx)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	wallet := models.PlayerWallet{
 | |
| 		CreatedAt: now,
 | |
| 		UpdatedAt: now,
 | |
| 		ID:        int(player.Id),
 | |
| 	}
 | |
| 	err = wallet.Insert(tx)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	tx.Commit()
 | |
| 	return &player, nil
 | |
| }
 | |
| 
 | |
| type intAuthTokenReq struct {
 | |
| 	Token string `form:"intAuthToken,omitempty"`
 | |
| }
 | |
| 
 | |
| func (p *playerController) getIntAuthToken(c *gin.Context) string {
 | |
| 	var req intAuthTokenReq
 | |
| 	err := c.ShouldBindWith(&req, binding.FormPost)
 | |
| 	api.CErr(c, err)
 | |
| 	if err != nil || "" == req.Token {
 | |
| 		c.Set(api.RET, Constants.RetCode.InvalidRequestParam)
 | |
| 		return ""
 | |
| 	}
 | |
| 	return req.Token
 | |
| }
 | |
| 
 | |
| type tel struct {
 | |
| 	Mobile     string `json:"mobile"`
 | |
| 	Nationcode string `json:"nationcode"`
 | |
| }
 | |
| 
 | |
| type captchaReq struct {
 | |
| 	Ext    string     `json:"ext"`
 | |
| 	Extend string     `json:"extend"`
 | |
| 	Params *[2]string `json:"params"`
 | |
| 	Sig    string     `json:"sig"`
 | |
| 	Sign   string     `json:"sign"`
 | |
| 	Tel    *tel       `json:"tel"`
 | |
| 	Time   int64      `json:"time"`
 | |
| 	Tpl_id int        `json:"tpl_id"`
 | |
| }
 | |
| 
 | |
| func sendSMSViaVendor(mobile string, nationcode string, captchaCode string) int {
 | |
| 	tel := &tel{
 | |
| 		Mobile:     mobile,
 | |
| 		Nationcode: nationcode,
 | |
| 	}
 | |
| 	var captchaExpireMin string
 | |
| 	if Conf.General.ServerEnv == SERVER_ENV_TEST {
 | |
| 		captchaExpireMin = "0.5" // Hardcoded
 | |
| 	} else {
 | |
| 		captchaExpireMin = strconv.Itoa(int(ConstVals.Player.CaptchaExpire) / 60000000000)
 | |
| 	}
 | |
| 	params := [2]string{captchaCode, captchaExpireMin}
 | |
| 	appkey := "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // TODO: Should read from config file!
 | |
| 	rand := strconv.Itoa(utils.Rand.Number(1000, 9999))
 | |
| 	now := utils.UnixtimeSec()
 | |
| 
 | |
| 	hash := sha256.New()
 | |
| 	hash.Write([]byte("appkey=" + appkey + "&random=" + rand + "&time=" + strconv.FormatInt(now, 10) + "&mobile=" + mobile))
 | |
| 	md := hash.Sum(nil)
 | |
| 	sig := hex.EncodeToString(md)
 | |
| 
 | |
| 	reqData := &captchaReq{
 | |
| 		Ext:    "",
 | |
| 		Extend: "",
 | |
| 		Params: ¶ms,
 | |
| 		Sig:    sig,
 | |
| 		Sign:   "YYYYYYYYYYYYYYYYY",
 | |
| 		Tel:    tel,
 | |
| 		Time:   now,
 | |
| 		Tpl_id: 207399,
 | |
| 	}
 | |
| 	reqDataString, err := json.Marshal(reqData)
 | |
| 	req := bytes.NewBuffer([]byte(reqDataString))
 | |
| 	if err != nil {
 | |
| 		Logger.Info("json marshal", zap.Any("err:", err))
 | |
| 		return -1
 | |
| 	}
 | |
| 	resp, err := http.Post("https://yun.tim.qq.com/v5/tlssmssvr/sendsms?sdkappid=uuuuuuuuuuuuuuuuuuuuuuuu&random="+rand,
 | |
| 		"application/json",
 | |
| 		req)
 | |
| 	if err != nil {
 | |
| 		Logger.Info("resp", zap.Any("err:", err))
 | |
| 	}
 | |
| 	defer resp.Body.Close()
 | |
| 	respBody, err := ioutil.ReadAll(resp.Body)
 | |
| 	if err != nil {
 | |
| 		Logger.Info("body", zap.Any("response body err:", err))
 | |
| 	}
 | |
| 	type bodyStruct struct {
 | |
| 		Result int `json:"result"`
 | |
| 	}
 | |
| 	var body bodyStruct
 | |
| 	json.Unmarshal(respBody, &body)
 | |
| 	return body.Result
 | |
| }
 |