func handleAppDemo(w http.ResponseWriter, r *http.Request) { log.Debug("Visit: %s", r.Proto+r.Host+r.RequestURI) r.ParseForm() var data struct { AccessToken string OpenID string TimeStamp string Nonce string Signature string ShareOpenID string } data.AccessToken = strings.Join(r.Form["access_token"], "") data.OpenID = strings.Join(r.Form["openid"], "") data.TimeStamp = strings.Join(r.Form["timestamp"], "") data.Nonce = strings.Join(r.Form["nonce"], "") data.ShareOpenID = strings.Join(r.Form["shareOpenID"], "") data.Signature = weixin.MakeSignature_js(data.TimeStamp, data.Nonce, weixin.Profile().JsApiTicket, "http://"+r.Host+r.RequestURI) path := baseDir + "/htdoc/app/demo.html" tpl, err := template.ParseFiles(path) if err != nil { log.Debug(err.Error()) return } err = tpl.Execute(w, data) if err != nil { log.Debug(err.Error()) return } }
//作为一个代理访问微信web的api(等弄明白js咋个跨域就不用这个了) func handleWxApi(w http.ResponseWriter, r *http.Request) { log.Debug("Visit: %s", r.RequestURI) url := r.RequestURI url = strings.Replace(url, "/wx/api/", "https://api.weixin.qq.com/", 1) log.Debug("API: %s", url) res, err := http.Get(url) if err != nil { log.Debug(err.Error()) return } result, _ := ioutil.ReadAll(res.Body) res.Body.Close() log.Debug("API_RET: %s", string(result)) w.Write(result) }
func LoadConfig() { config_file := flag.String("config", "", "Use -config <filesource>") config_url := flag.String("config_url", "", "Use -config_url <filesource>") flag.Parse() utils.GetParentDirectory(utils.GetCurrentDirectory()) if len(*config_file) > 1 { fmt.Println("读取配置文件: " + *config_file) utils.LoadJsonFile(*config_file, C) } else if len(*config_url) > 1 { fmt.Println("读取配置文件: " + *config_url) utils.LoadJsonURL(*config_url, C) } log.Release = (C.Release != 0) Release = (C.Release != 0) if Release { log.Trace("Release模式运行") } else { log.Trace("Debug模式运行") } //一些特殊值 if C.LoginTimeOut <= 1 { C.LoginTimeOut = 3 } log.Debug("%v", C) }
func TestSinaAuth() { mux := http.NewServeMux() mux.HandleFunc("/sina", handleRoot) mux.HandleFunc("/sina/authorize", handleAuthorize) go http.ListenAndServe(":3000", mux) log.Debug("测试连接在 127.0.0.1:3000") }
func (p *Processor) Handler(reciver network.IAgent, data []byte, clientData interface{}) (bool, error) { if len(data) < 2 { return false, errors.New("protobuf data too short") } nameLen := int(data[0])*265 + int(data[1]) if len(data) < 2+nameLen { return false, errors.New("protobuf data too short") } msgName := string(data[2 : nameLen+2]) //log.Dev("Recv Msg: %s", msgName) i, ok := p.msgInfo[msgName] if !ok { s := fmt.Sprintf("message %s not registered", msgName) log.Fatal(s) log.Debug("%v", p.msgInfo) return false, errors.New(s) } if i.msgHandler == nil { s := fmt.Sprintf("message %s not handler", msgName) log.Fatal(s) return false, errors.New(s) } msg := reflect.New(i.msgType.Elem()).Interface().(proto.Message) if e := proto.Unmarshal(data[nameLen+2:], msg); e != nil { return false, e } if i.msgHandler != nil { i.msgHandler(reciver, i.msgType.Elem(), msg, []interface{}{data, clientData}) } return true, nil }
func (tcpConn *TCPConn) doWrite(b []byte) { if len(tcpConn.writeChan) == cap(tcpConn.writeChan) { log.Debug("close conn: channel full") tcpConn.doDestroy() return } tcpConn.writeChan <- b }
func TestProtorpc() { go startProtorpcService() echoClient, err := Msg.DialEchoService("tcp", NetworkAddr) for err != nil { log.Error("连接服务失败 :%v", err) time.Sleep(time.Second * 1) echoClient, err = Msg.DialEchoService("tcp", NetworkAddr) } echoClient, err = Msg.DialEchoService("tcp", NetworkAddr) wg := new(sync.WaitGroup) for i := 0; i < 10; i++ { wg.Add(1) go func(i int) { defer wg.Done() log.Debug("RPC Call Begin..." + strconv.Itoa(i)) reply, err := echoClient.Echo(&Msg.EchoRequest{Msg: proto.String("Hello!" + strconv.Itoa(i))}) if err != nil { log.Error("EchoTwice: %v", err) } log.Trace(reply.GetMsg()) log.Debug("RPC Call Finish..." + strconv.Itoa(i)) }(i) } /* client, err := protorpc.Dial("tcp", `127.0.0.1:9527`) if err != nil { log.Fatal("protorpc.Dial: %v", err) } defer client.Close() echoClient1 := &Msg.EchoServiceClient{client} echoClient2 := &Msg.EchoServiceClient{client} reply, err = echoClient1.Echo(args) log.Trace(reply.GetMsg()) reply, err = echoClient2.EchoTwice(args) log.Trace(reply.GetMsg()) _, _ = reply, err */ wg.Wait() echoClient.Close() }
func (wsConn *WSConn) doWrite(b []byte) { //WHY: 消息满了就要关闭链接,没有道理啊..... if len(wsConn.writeChan) == cap(wsConn.writeChan) { log.Debug("close conn: channel full") wsConn.doDestroy() return } wsConn.writeChan <- b }
func tcpHandleMsg(agent network.IAgent, msgType reflect.Type, message interface{}, data []interface{}) { if "Msg.EchoMsg" != msgType.String() { return } msg := message.(*Msg.EchoMsg) log.Debug(reflect.TypeOf(agent).String() + ":" + msg.GetEchoString()) //msg.EchoString = proto.String("i will be back.....") //agent.WriteMsg(msg) }
//实现net.http.handler接口 //每次HTTP请求的时候被调用,用于产生链接 func (handler *WSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer utils.PrintPanicStack() log.Trace("new connect from %s(url:%s)", r.RemoteAddr, r.RequestURI) if r.Method != "GET" { http.Error(w, "Method not allowed", 405) return } conn, err := handler.upgrader.Upgrade(w, r, nil) if err != nil { log.Debug("upgrade error: %v", err) return } handler.wg.Add(1) defer handler.wg.Done() handler.mutexConns.Lock() if handler.conns == nil { handler.mutexConns.Unlock() conn.Close() log.Debug("upgrade error: nil") return } if len(handler.conns) >= handler.maxConnNum { handler.mutexConns.Unlock() conn.Close() log.Debug("too many connections") return } handler.conns[conn] = struct{}{} handler.mutexConns.Unlock() wsConn := newWSConn(conn, handler.pendingWriteNum) agent := handler.newAgent(wsConn) agent.Run() // cleanup wsConn.Close() handler.mutexConns.Lock() delete(handler.conns, conn) handler.mutexConns.Unlock() agent.OnClose() }
func gateHandleMsg(agant network.IAgent, msgType reflect.Type, message interface{}, data []interface{}) { if "Msg.EchoMsg" != msgType.String() { return } msg := message.(*Msg.EchoMsg) log.Debug(msg.GetEchoString()) msg.EchoString = proto.String("i will be back.....") agant.WriteMsg(msg) msg.EchoString = proto.String("i am back.....") agant.WriteMsg(msg) }
//获取微信服务器的Token func RefreshAccessToken(loop bool) { type wxJsonToken struct { WeiXinError AccessToken string `json:"access_token"` ExpiresIn int `json:"expires_in"` } wxToken := new(WeiXinAccessToken) if !wxToken.Load(wxProfile.AppID) { wxToken.ExpireIn = 0 wxProfile.AccessToken = "" } else { wxProfile.AccessToken = wxToken.AccessToken log.Trace("加载数据库微信Accesstoken: %s", wxProfile.AccessToken) } for loop { newSec := time.Now().UnixNano() / time.Second.Nanoseconds() for newSec < wxToken.ExpireIn { time.Sleep(time.Second) newSec = time.Now().UnixNano() / time.Second.Nanoseconds() } wxProfile.AccessToken = "" log.Trace("微信Accesstoken过期,重新获取Token") url := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET" url = strings.Replace(url, "APPID", wxProfile.AppID, -1) url = strings.Replace(url, "APPSECRET", wxProfile.AppSecret, -1) //log.Debug(url) res, err := http.Get(url) if err != nil { log.Error("获取Token失败 %v", err) } result, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { log.Error("解析Token失败 %v", err) } log.Debug(string(result)) var jsonData wxJsonToken if err := json.Unmarshal(result, &jsonData); err == nil { wxProfile.AccessToken = jsonData.AccessToken log.Trace("收到Token: %s", wxProfile.AccessToken) wxToken.AccessToken = jsonData.AccessToken wxToken.ExpireIn = newSec + int64(jsonData.ExpiresIn) - 60*10 wxToken.Save() } else { log.Error(err.Error()) } } }
func DoOAuth2(service *AuthService, accid uint64, cb AuthCallBackFunc) (string, error) { if service == nil { err := errors.New("SinaOAuth2没有初始化") cb(nil, accid, err) return "", err } if _, ok := service.callback[accid]; ok { err := errors.New("accid冲突") cb(nil, accid, err) return "", err } service.callback[accid] = cb log.Debug("授权回调地址" + service.oauthCfg.RedirectURL) return service.oauthCfg.AuthCodeURL(strconv.FormatUint(accid, 10)), nil }
//刷新JsApiTicket func RefreshJsApiTicket(loop bool) { type wxJsonToken struct { WeiXinError JsApiTicket string `json:"ticket"` ExpiresIn int `json:"expires_in"` } wxTicket := new(WeiXinJsApiTicket) if !wxTicket.Load(wxProfile.AppID) { wxTicket.ExpireIn = 0 } else { wxProfile.JsApiTicket = wxTicket.JsApiTicket log.Trace("加载数据库微信JsApiTicket: %s", wxProfile.JsApiTicket) } for loop { newSec := time.Now().UnixNano() / time.Second.Nanoseconds() for newSec < wxTicket.ExpireIn || len(wxProfile.AccessToken) == 0 { time.Sleep(time.Second) newSec = time.Now().UnixNano() / time.Second.Nanoseconds() } log.Trace("微信JsApiTicket过期,重新获取JsApiTicket") url := "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi" url = strings.Replace(url, "ACCESS_TOKEN", wxProfile.AccessToken, -1) //log.Debug(url) res, err := http.Get(url) if err != nil { log.Error("获取JsApiTicket失败 %v", err) } result, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { log.Error("解析JsApiTicket失败 %v", err) } log.Debug(string(result)) var jsonData wxJsonToken if err := json.Unmarshal(result, &jsonData); err == nil { wxProfile.JsApiTicket = wxTicket.JsApiTicket log.Trace("收到JsApiTicket: %s", wxProfile.AccessToken) wxTicket.JsApiTicket = jsonData.JsApiTicket wxTicket.ExpireIn = newSec + int64(jsonData.ExpiresIn) - 60*10 wxTicket.Save() } else { log.Error(err.Error()) } } }
//发送消息 func (a *TCPAgent) WriteMsg(msg interface{}) { if a.protobufProcessor != nil { data, err := a.protobufProcessor.PackMsg(msg.(proto.Message)) if err != nil { log.Debug("protobuf pack msg error %v", err) return } a.conn.WriteMsg(data) } else { data := msg.([]byte) if data != nil { a.conn.WriteMsg(data) } else { a.Error("发送消息没有合适的处理器") } } }
func UserAuthorized(state string, token *weixin.WebAccessToken, w http.ResponseWriter, r *http.Request) bool { key := "NikeName:" + token.OpenID ret, err := nosql.Redis.Get(key).Result() if err != nil { userinfo := weixin.GetUserInfo(token.OpenID, true) if userinfo != nil { ret, err = nosql.Redis.Set(key, userinfo.NikeName, 0).Result() if err != nil { log.Debug(err.Error() + " | " + ret) } else { log.Trace("App: %s 有人授权了(new)name: %s", state, userinfo.NikeName) } } } else { log.Trace("App: %s 有人授权了name: %s", state, ret) } return true }
//绑定端口,等待连接 func (server *TCPServer) run() { for { conn, err := server.ln.Accept() if err != nil { if server.closeFlag { return } else { log.Error("accept error: %v", err) continue } } //加入连接集合 server.mutexConns.Lock() if len(server.conns) >= server.MaxConnNum { server.mutexConns.Unlock() conn.Close() log.Debug("too many connections") continue } server.conns[conn] = struct{}{} server.mutexConns.Unlock() server.wg.Add(1) tcpConn := newTCPConn(conn, server.PendingWriteNum, server.msgParser) agent := server.NewAgent(tcpConn) go func() { agent.Run() //从连接集合中删除 tcpConn.Close() server.mutexConns.Lock() delete(server.conns, conn) server.mutexConns.Unlock() agent.OnClose() server.wg.Done() }() } }
func (a *WSAgent) Close() { log.Debug("主动关闭 WSAgent") a.conn.Close() }
func getUserInfo(token string, openID string, sns bool, cache bool) *WeiXinUserInfo { key := "UserInfo:" + openID if cache { ret, err := nosql.Redis.Get(key).Result() if err == nil { userinfo := &WeiXinUserInfo{} err = json.Unmarshal([]byte(ret), userinfo) if err == nil { return userinfo } else { log.Error(err.Error()) } } else { log.Error(err.Error()) } } if wxProfile == nil { log.Error("还没有获取AccessToken") return nil } if len(wxProfile.AccessToken) == 0 { log.Error("还没有获取AccessToken") return nil } url := "" if sns { url = "https://api.weixin.qq.com/sns/userinfo?access_token={{.AccessToken}}&openid={{.OpenID}}&lang=zh_CN" url = strings.Replace(url, "{{.AccessToken}}", token, -1) url = strings.Replace(url, "{{.OpenID}}", openID, -1) } else { url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={{.ACCESS_TOKEN}}&openid={{.OPENID}}&lang=zh_CN" url = strings.Replace(url, "{{.ACCESS_TOKEN}}", wxProfile.AccessToken, -1) url = strings.Replace(url, "{{.OPENID}}", openID, -1) } res, err := http.Get(url) if err != nil { log.Trace("请求URL: %s", url) log.Error("获取微信用户信息失败 %v", err) return nil } result, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { log.Error("解析微信用户信息失败 %v", err) return nil } log.Debug(string(result)) info := &WeiXinUserInfo{} if err := json.Unmarshal(result, info); err == nil { err = nosql.Redis.Set(key, string(result), 0).Err() if err != nil { log.Error("Redis Error: %s", err.Error()) } if checkWeiXinReturn(&(info.WeiXinError)) { return info } else { return info } } else { log.Error(err.Error()) } return nil }
func handleWeiXinRoot(w http.ResponseWriter, r *http.Request) { log.Debug("\n--") log.Debug("Visit: " + r.RequestURI) r.ParseForm() if !checkWeiXinUrlVailed(r) { w.WriteHeader(505) log.Trace("微信认证失败") return } if r.Method == "GET" { //微信服务器验证请求 echostr := strings.Join(r.Form["echostr"], "") fmt.Fprintf(w, echostr) log.Trace("微信认证成功") } else { log.Debug("其他请求 %v", r) result, _ := ioutil.ReadAll(r.Body) r.Body.Close() log.Debug("%s\n", result) revMsg := parseRecvWeiXinMsg(result) if revMsg == nil { return } if _, ok := wxProfile.msgCollection[revMsg.MsgId]; ok == true { log.Debug("过滤重复MsgID: %s", revMsg.MsgId) return } wxProfile.msgCollection[revMsg.MsgId] = true sendMsg := new(SendWeiXinMsg) sendMsg.FromUserName = wxProfile.OwnerID sendMsg.ToUserName = revMsg.FromUserName sendMsg.CreateTime = fmt.Sprintf("%d", time.Now().Second()) if wxProfile.ProcessMsg == nil { sendMsg.MsgType = "text" if revMsg.Content == "我是谁" { info := GetUserInfo(revMsg.FromUserName, true) if info != nil { sendMsg.Content = "你是: " + info.NikeName } else { sendMsg.Content = "不认识你哦..." } } else { sendMsg.Content = "回你: " + revMsg.Content } } else { wxProfile.ProcessMsg(revMsg, sendMsg) } bytes, err := xml.Marshal(sendMsg) if err != nil { w.WriteHeader(500) log.Error(err.Error()) return } else { w.WriteHeader(200) w.Write(bytes) log.Debug("微信返回: %s", string(bytes)) } } }
func (a *TCPAgent) Debug(format string, d ...interface{}) { log.Debug(a.description()+format, d...) }