mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 11:48:56 +00:00
278 lines
7.2 KiB
Go
278 lines
7.2 KiB
Go
package utils
|
|
|
|
import (
|
|
. "battle_srv/common"
|
|
. "battle_srv/configs"
|
|
"bytes"
|
|
"crypto/sha1"
|
|
. "dnmshared"
|
|
"encoding/json"
|
|
"fmt"
|
|
"go.uber.org/zap"
|
|
"io"
|
|
"io/ioutil"
|
|
"math/rand"
|
|
"net/http"
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
var WechatIns *wechat
|
|
var WechatGameIns *wechat
|
|
|
|
func InitWechat(conf WechatConfig) {
|
|
WechatIns = NewWechatIns(&conf, Constants.AuthChannel.Wechat)
|
|
}
|
|
|
|
func InitWechatGame(conf WechatConfig) {
|
|
WechatGameIns = NewWechatIns(&conf, Constants.AuthChannel.WechatGame)
|
|
}
|
|
|
|
func NewWechatIns(conf *WechatConfig, channel int) *wechat {
|
|
newWechat := &wechat{
|
|
config: conf,
|
|
channel: channel,
|
|
}
|
|
return newWechat
|
|
}
|
|
|
|
const ()
|
|
|
|
type wechat struct {
|
|
config *WechatConfig
|
|
channel int
|
|
}
|
|
|
|
// CommonError 微信返回的通用错误json
|
|
type CommonError struct {
|
|
ErrCode int64 `json:"errcode"`
|
|
ErrMsg string `json:"errmsg"`
|
|
}
|
|
|
|
// ResAccessToken 获取用户授权access_token的返回结果
|
|
type resAccessToken struct {
|
|
CommonError
|
|
|
|
AccessToken string `json:"access_token"`
|
|
ExpiresIn int64 `json:"expires_in"`
|
|
RefreshToken string `json:"refresh_token"`
|
|
OpenID string `json:"openid"`
|
|
Scope string `json:"scope"`
|
|
}
|
|
|
|
// Config 返回给用户jssdk配置信息
|
|
type JsConfig struct {
|
|
AppID string `json:"app_id"`
|
|
Timestamp int64 `json:"timestamp"`
|
|
NonceStr string `json:"nonce_str"`
|
|
Signature string `json:"signature"`
|
|
}
|
|
|
|
// resTicket 请求jsapi_tikcet返回结果
|
|
type resTicket struct {
|
|
CommonError
|
|
|
|
Ticket string `json:"ticket"`
|
|
ExpiresIn int64 `json:"expires_in"`
|
|
}
|
|
|
|
func (w *wechat) GetJsConfig(uri string) (config *JsConfig, err error) {
|
|
config = new(JsConfig)
|
|
var ticketStr string
|
|
ticketStr, err = w.getTicket()
|
|
if err != nil {
|
|
return
|
|
}
|
|
nonceStr := randomStr(16)
|
|
timestamp := UnixtimeSec()
|
|
str := fmt.Sprintf("jsapi_ticket=%s&noncestr=%s×tamp=%d&url=%s", ticketStr, nonceStr, timestamp, uri)
|
|
sigStr := signature(str)
|
|
|
|
config.AppID = w.config.AppID
|
|
config.NonceStr = nonceStr
|
|
config.Timestamp = timestamp
|
|
config.Signature = sigStr
|
|
return
|
|
}
|
|
|
|
// TODO add cache, getTicket 获取jsapi_ticket
|
|
func (w *wechat) getTicket() (ticketStr string, err error) {
|
|
var ticket resTicket
|
|
ticket, err = w.getTicketFromServer()
|
|
if err != nil {
|
|
return
|
|
}
|
|
ticketStr = ticket.Ticket
|
|
return
|
|
}
|
|
|
|
func (w *wechat) GetOauth2Basic(authcode string) (result resAccessToken, err error) {
|
|
var accessTokenURL string
|
|
if w.channel == Constants.AuthChannel.WechatGame {
|
|
accessTokenURL = w.config.ApiProtocol + "://" + w.config.ApiGateway + "/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
|
|
}
|
|
if w.channel == Constants.AuthChannel.Wechat {
|
|
accessTokenURL = w.config.ApiProtocol + "://" + w.config.ApiGateway + "/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"
|
|
}
|
|
urlStr := fmt.Sprintf(accessTokenURL, w.config.AppID, w.config.AppSecret, authcode)
|
|
Logger.Info("urlStr", zap.Any(":", urlStr))
|
|
response, err := get(urlStr)
|
|
if err != nil {
|
|
return
|
|
}
|
|
err = json.Unmarshal(response, &result)
|
|
if err != nil {
|
|
Logger.Info("GetOauth2Basic marshal error", zap.Any("err", err))
|
|
return
|
|
}
|
|
if result.ErrCode != 0 {
|
|
err = fmt.Errorf("GetOauth2Basic error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// UserInfo 用户授权获取到用户信息
|
|
type UserInfo struct {
|
|
CommonError
|
|
OpenID string `json:"openid"`
|
|
Nickname string `json:"nickname"`
|
|
Sex int32 `json:"sex"`
|
|
Province string `json:"province"`
|
|
City string `json:"city"`
|
|
Country string `json:"country"`
|
|
HeadImgURL string `json:"headimgurl"`
|
|
Privilege []string `json:"privilege"`
|
|
Unionid string `json:"unionid"`
|
|
}
|
|
|
|
func (w *wechat) GetMoreInfo(accessToken string, openId string) (result UserInfo, err error) {
|
|
userInfoURL := w.config.ApiProtocol + "://" + w.config.ApiGateway + "/sns/userinfo?appid=%s&access_token=%s&openid=%s&lang=zh_CN"
|
|
urlStr := fmt.Sprintf(userInfoURL, w.config.AppID, accessToken, openId)
|
|
response, err := get(urlStr)
|
|
if err != nil {
|
|
return
|
|
}
|
|
err = json.Unmarshal(response, &result)
|
|
if err != nil {
|
|
Logger.Info("GetMoreInfo marshal error", zap.Any("err", err))
|
|
return
|
|
}
|
|
if result.ErrCode != 0 {
|
|
err = fmt.Errorf("GetMoreInfo error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// HTTPGet get 请求
|
|
func get(uri string) ([]byte, error) {
|
|
response, err := http.Get(uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
if response.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("http get error : uri=%v , statusCode=%v", uri, response.StatusCode)
|
|
}
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return body, err
|
|
}
|
|
|
|
// PostJSON post json 数据请求
|
|
func post(uri string, obj interface{}) ([]byte, error) {
|
|
jsonData, err := json.Marshal(obj)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
jsonData = bytes.Replace(jsonData, []byte("\\u003c"), []byte("<"), -1)
|
|
jsonData = bytes.Replace(jsonData, []byte("\\u003e"), []byte(">"), -1)
|
|
jsonData = bytes.Replace(jsonData, []byte("\\u0026"), []byte("&"), -1)
|
|
|
|
body := bytes.NewBuffer(jsonData)
|
|
response, err := http.Post(uri, "application/json;charset=utf-8", body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("http get error : uri=%v , statusCode=%v", uri, response.StatusCode)
|
|
}
|
|
return ioutil.ReadAll(response.Body)
|
|
}
|
|
|
|
// Signature sha1签名
|
|
func signature(params ...string) string {
|
|
sort.Strings(params)
|
|
h := sha1.New()
|
|
for _, s := range params {
|
|
io.WriteString(h, s)
|
|
}
|
|
return fmt.Sprintf("%x", h.Sum(nil))
|
|
}
|
|
|
|
// RandomStr 随机生成字符串
|
|
func randomStr(length int) string {
|
|
str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
bytes := []byte(str)
|
|
result := []byte{}
|
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
for i := 0; i < length; i++ {
|
|
result = append(result, bytes[r.Intn(len(bytes))])
|
|
}
|
|
return string(result)
|
|
}
|
|
|
|
// getTicketFromServer 强制从服务器中获取ticket
|
|
func (w *wechat) getTicketFromServer() (ticket resTicket, err error) {
|
|
var accessToken string
|
|
accessToken, err = w.getAccessTokenFromServer()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
getTicketURL := w.config.ApiProtocol + "://" + w.config.ApiGateway + "/cgi-bin/ticket/getticket?access_token=%s&type=jsapi"
|
|
var response []byte
|
|
url := fmt.Sprintf(getTicketURL, accessToken)
|
|
response, err = get(url)
|
|
err = json.Unmarshal(response, &ticket)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if ticket.ErrCode != 0 {
|
|
err = fmt.Errorf("getTicket Error : errcode=%d , errmsg=%s", ticket.ErrCode, ticket.ErrMsg)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// GetAccessTokenFromServer 强制从微信服务器获取token
|
|
func (w *wechat) getAccessTokenFromServer() (accessToken string, err error) {
|
|
AccessTokenURL := w.config.ApiProtocol + "://" + w.config.ApiGateway + "/cgi-bin/token"
|
|
url := fmt.Sprintf("%s?grant_type=client_credential&appid=%s&secret=%s", AccessTokenURL, w.config.AppID, w.config.AppSecret)
|
|
var body []byte
|
|
body, err = get(url)
|
|
if err != nil {
|
|
return
|
|
}
|
|
var r resAccessToken
|
|
err = json.Unmarshal(body, &r)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if r.ErrMsg != "" {
|
|
err = fmt.Errorf("get access_token error : errcode=%v , errormsg=%v", r.ErrCode, r.ErrMsg)
|
|
return
|
|
}
|
|
|
|
accessToken = r.AccessToken
|
|
return
|
|
}
|