function.go 9.46 KB
package logic

import (
	"HttpServer/jsonconf"
	"HttpServer/redishandler"
	"bytes"
	"common/logger"
	"common/redis"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"time"

	"github.com/astaxie/beego/httplib"
)

func SetHeader(w http.ResponseWriter) {
	w.Header().Set("Access-Control-Allow-Origin", "*") //允许访问所有域
	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Access-Control-Allow-Headers", "Content-Type,Uuid")
}

func SaveUserInfo(data *UserData) error {

	savestr, err := json.Marshal(data)
	if err != nil {
		return err
	}

	err = redishandler.GetRedisClient().HSet(redis.USER_DATA_KEY, data.Openid, string(savestr))

	return err
}

func SaveUserInfoByMysql(data UserData) error {

	savestr, err := json.Marshal(data)
	if err != nil {
		return err
	}

	err = redishandler.GetRedisClient().HSet(redis.USER_DATA_KEY, data.Openid, string(savestr))

	return err
}

func GetUserInfo(openid string) (*UserData, error) {

	//先判断用户是否存在 不存在创建新的用户
	isexist, err := redishandler.GetRedisClient().HExists(redis.USER_DATA_KEY, openid)
	if err != nil {
		logger.Error("redis failed err=%v", err)
		return nil, err
	}

	//返回
	//if !isexist {
	//	return nil,errors.New("new user!")
	//}

	tmp := new(UserData)
	if !isexist {
		//不存在
		//属于新登录的玩家数据
		//err = tmp.InitUserInfo(openid)
		return nil, errors.New("new user!")
	} else {
		//已经登陆过了 需要获取玩家数据
		data, err := redishandler.GetRedisClient().HGet(redis.USER_DATA_KEY, openid)
		if err != nil {
			return nil, err
		}

		err = json.Unmarshal([]byte(data), tmp)
		if err != nil {
			return nil, err
		}
	}

	return tmp, nil
}

func (u *UserData) InitUserInfo(openid string) error {
	nowtime := time.Now()
	u.Openid = openid
	u.SignRound = 1
	u.IsSign = 0
	u.LastGetTime = 0
	u.LeftCnt = DAILY_FETCH_CNT
	u.MaxLevel = 1
	u.Property = 0
	u.SingDay = 0
	u.PassLvGold = 0
	u.TodaySec = int(time.Date(nowtime.Year(), nowtime.Month(), nowtime.Day(), 0, 0, 0, 0, nowtime.Location()).Unix())
	u.TotalFetchCnt = 0 //用于计算当前领取次数
	u.PlayerData = ""
	u.RegTime = int(time.Now().Unix())

	err := SaveUserInfo(u)
	if err != nil {
		logger.Error("InitUserInfo err=%v", err)
	}
	return err
}

//计算当前领取宝箱需要的数值
func (u *UserData) CalcCurLe() int64 {
	cfg := jsonconf.GetGoldChestConfig(u.TotalFetchCnt + 1)
	if cfg == nil {
		logger.Error("CalcCurLe failed u=%v", u)
		return 0
	}

	return cfg.Score
}

//计算速率
func (u *UserData) CalcSpeed() int64 {
	cfg := jsonconf.GetGoldGunsConfig(u.MaxLevel)
	if cfg == nil {
		logger.Error("CalcSpeed failed u=%v", u)
		return 0
	}
	return cfg.Speed
}

//计算物资
func (u *UserData) CalcProperty() {
	nowtime := int(time.Now().Unix())
	if nowtime < u.LastGetTime {
		logger.Error("CalcProperty err n=%v,l=%v", nowtime, u.LastGetTime)
	} else if nowtime >= u.LastGetTime+60*3 {
		//超过三次请求了 不再计算离线收益

	} else {
		//计算一下离线收益
		mult := nowtime - u.LastGetTime
		speed := u.CalcSpeed()
		u.Property += int64(mult) * speed
	}
	u.LastGetTime = nowtime

	//判断跨天
	if nowtime < u.TodaySec {
		logger.Error("CalcProperty err2")
		nowtt := time.Now()
		u.TodaySec = int(time.Date(nowtt.Year(), nowtt.Month(), nowtt.Day(), 0, 0, 0, 0, nowtt.Location()).Unix())
	} else {
		if nowtime > u.TodaySec+86400 {
			//跨天了
			nowtt := time.Now()
			u.TodaySec = int(time.Date(nowtt.Year(), nowtt.Month(), nowtt.Day(), 0, 0, 0, 0, nowtt.Location()).Unix())
			u.LeftCnt = DAILY_FETCH_CNT
			u.IsSign = 0
			if u.SingDay == 7 {
				u.SingDay = 0
				u.SignRound++
			}
			u.PassLvGold = 0
		}
	}
	//保存
	err := SaveUserInfo(u)
	if err != nil {
		logger.Error("CalcProperty err=%v", err)
	}
}

func GetOpenid(code string) (string, error) {
	url := GETTOUTIAOOPENIDURL + "?appid=" + TOUTIAOAPPID + "&secret=" + TOUTIAOSECRET + "&code=" + code
	res, err := http.Get(url)
	if err != nil {
		logger.Error("GetOpenid err=%v", err)
		return "", err
	}
	result, _ := ioutil.ReadAll(res.Body)
	defer res.Body.Close()

	var tmp GetOpenidResp
	err = json.Unmarshal(result, &tmp)
	if err != nil {
		logger.Error("GetOpenid err=%v", err)
		return "", err
	}

	if tmp.Errmsg != "" {
		logger.Error("GetOpenid err=%v", tmp.Errmsg)
		return "", errors.New(tmp.Errmsg)
	}

	//保存头条session key
	go SetBytedanceSessionKey(tmp.Openid, tmp.Session_key)

	return tmp.Openid, nil
}

func GetAccessToken() (string, error) {
	//首先从缓存取
	var token string
	token, err := redishandler.GetRedisClient().GetString(redis.GAME_ACCESS_TOKEN)
	if err == nil {
		return token, nil
	}

	//如果没找到 则取取
	url := GETTOUTIAOACCESSTOKENURL + "?appid=" + TOUTIAOAPPID + "&secret=" + TOUTIAOSECRET + "&grant_type=client_credential"
	res, err := http.Get(url)
	if err != nil {
		logger.Error("GetAccessToken err=%v", err)
		return "", err
	}
	result, _ := ioutil.ReadAll(res.Body)
	defer res.Body.Close()

	var tmp GetAccessTokenResp
	err = json.Unmarshal([]byte(result), &tmp)
	if err != nil {
		logger.Error("GetAccessToken err=%v", err)
		return "", err
	}

	if tmp.Access_token == "" {
		logger.Error("GetAccessToken err=%v", tmp.Errmsg)
		return "", errors.New(tmp.Errmsg)
	}

	//保存token缓存
	expiretime := tmp.Expires_in
	redishandler.GetRedisClient().SetString(redis.GAME_ACCESS_TOKEN, tmp.Access_token)
	redishandler.GetRedisClient().Expire(redis.GAME_ACCESS_TOKEN, expiretime-10)

	return tmp.Access_token, nil
}

func DoHttpPost(bys []byte, url string) (string, error) {
	body := bytes.NewBuffer(bys)

	res, err := http.Post(url, "application/json;charset=utf-8", body)
	if err != nil {
		logger.Error("DoHttpPost failed err=%v", err)
		return "", err
	}

	result, _ := ioutil.ReadAll(res.Body)
	defer res.Body.Close()

	return string(result), nil
}

func GetCoinFromToutiao(openid string, deviceid int) (int, error) {
	accesstoken, _ := GetAccessToken()
	url := GETTOUTIAOCOINURL + "?access_token=" + accesstoken + "&open_id=" + openid + "&device_id=" + strconv.Itoa(deviceid)
	res, err := http.Get(url)
	if err != nil {
		logger.Error("GetAccessToken err=%v", err)
		return 0, err
	}
	result, _ := ioutil.ReadAll(res.Body)
	defer res.Body.Close()

	var tmp AddcointotoutiaoResp
	err = json.Unmarshal(result, &tmp)
	if err != nil {
		logger.Error("GetAccessToken err=%v", err)
		return 0, err
	}
	if tmp.Errcode != 0 {
		logger.Error("GetAccessToken err=%v", tmp.Errmsg)
		return 0, errors.New(tmp.Errmsg)
	}
	return tmp.Data, nil
}

func AddCoinToTouTiao(openid string, deviceid, amount int, descr string, btype string, appname string) (int, int, int, bool, error) {

	gold_coin_extra_add := 0
	gold_coin_extra_limit := false

	acctoken, err := GetAccessToken()
	if err != nil {
		logger.Error("AddCoinToTouTiao err=%v", err)
		return 0, 0, gold_coin_extra_add, gold_coin_extra_limit, err
	}

	//获取		GlobalID
	globalid, err := GetBytedanceGlobalID(acctoken, openid)
	if err != nil {
		logger.Error("AddCoinToTouTiao GetBytedanceGlobalID err=%v", err)
		return 0, 0, gold_coin_extra_add, gold_coin_extra_limit, err
	}

	var reqdata AddcointotoutiaoReq
	reqdata.Access_token = acctoken
	reqdata.Amount = amount
	reqdata.Bonus_type = btype
	reqdata.Description = descr
	//reqdata.Device_id = deviceid
	reqdata.Open_id = openid
	reqdata.GlobalID = globalid

	aidconfig := jsonconf.GetAidsConfig(appname)
	if aidconfig != nil {
		reqdata.TaskID = aidconfig.TaskID
		reqdata.Extra.TaskKey = aidconfig.TaskKey
		if aidconfig.Description != "" {
			reqdata.Description = fmt.Sprintf("%s+%d", aidconfig.Description, amount)
		}
	}

	logger.Info("AddCoinToTouTiao req=%v", reqdata)
	bys, err := json.Marshal(&reqdata)
	if err != nil {
		logger.Error("AddCoinToTouTiao failed=%v", err)
		return 0, 0, gold_coin_extra_add, gold_coin_extra_limit, err
	}

	//计算签名
	//signbody, _ := json.Marshal(reqdata)
	signature := CreateCommonBytedanceSign(bys, openid)
	apiurl := ADDCOINTOTOUTIAOURL + "?signature=" + signature

	res, err := BeegoHttpPost(apiurl, reqdata)
	if err != nil {
		logger.Error("AddCoinToTouTiao failed=%v", err)
		return 0, 0, gold_coin_extra_add, gold_coin_extra_limit, err
	}

	var resp AddcointotoutiaoResp
	err = json.Unmarshal([]byte(res), &resp)
	if err != nil {
		logger.Error("AddCoinToTouTiao failed=%v", err)
		return 0, 0, gold_coin_extra_add, gold_coin_extra_limit, err
	}

	if resp.Errcode != 0 {
		logger.Error("AddCoinToTouTiao failed=%v", resp)
		return 0, 0, gold_coin_extra_add, gold_coin_extra_limit, errors.New(resp.Errmsg)
	}

	newcoin, err := GetCoinFromToutiao(openid, 1)
	if err != nil {
		logger.Error("AddCoinToTouTiao failed=%v", err)
		return 0, 0, gold_coin_extra_add, gold_coin_extra_limit, err
	}

	gold_coin_extra_add = resp.Extra_ADD
	gold_coin_extra_limit = resp.Extra_Limit

	return resp.Data, newcoin, gold_coin_extra_add, gold_coin_extra_limit, nil
}

func BeegoHttpPost(url string, reqdata AddcointotoutiaoReq) (string, error) {

	req := httplib.Post(url)
	req.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})

	if TOUTIAOENV == 0 {
		req.Header("x-use-ppe", "1")
		req.Header("x-tt-env", "ppe_gold_center_growth")
		logger.Error("BeegoHttpPost TOUTIAOENV:", TOUTIAOENV)
	}

	//logtest
	req.JSONBody(&reqdata)

	result, err := req.String()
	if err != nil {
		logger.Error("BeegoHttpPost failed err=%v", err)
		return "", err
	}

	if TOUTIAOENV == 0 {
		rep, _ := req.Response()
		logid := rep.Header.Get("x-tt-logid")
		logger.Error("logid::", logid)
		logger.Error("url::", url)
		logger.Error("result::", string(result))
		logger.Error("reqdata::", reqdata)
	}

	return string(result), nil
}