func clientCall(min int32) { startTime := currentTimeMillis() transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory()) protocolFactory := thrift.NewTBinaryProtocolFactoryDefault() transport, err := thrift.NewTSocket(NetworkAddr) for err != nil { transport, err = thrift.NewTSocket(NetworkAddr) if err != nil { log.Error("error resolving address:", err) } time.Sleep(1 * time.Second) } useTransport := transportFactory.GetTransport(transport) client := demo.NewRpcServiceClientFactory(useTransport, protocolFactory) if err := transport.Open(); err != nil { log.Error("Error opening socket to 127.0.0.1:19090", " ", err) return } defer transport.Close() for i := min; i < min+3; i++ { r1, e1 := client.Add(i, i+1) log.Trace("%d %s %v %v", i, "Call->", r1, e1) } endTime := currentTimeMillis() log.Trace("Program exit. time->", endTime, startTime, (endTime - startTime)) }
func LoadJsonFile(fileName string, conf interface{}) bool { //confName := "" if !strings.HasSuffix(fileName, ".json") { fileName = fileName + ".json" //confName = fileName } else { //confName = fileName[:len(fileName)-len(".json")] } r, err := os.Open(fileName) if err != nil { log.Error(err.Error()) return false } buf := make([]byte, 1024*1024) n, err := r.Read(buf) if err != nil { log.Error(err.Error()) return false } str := string(buf[:n]) //str = strings.Replace(str, "//", "######", -1) //str = strings.Replace(str, "/", "\\/", -1) //str = strings.Replace(str, "######", "//", -1) err = json.Unmarshal([]byte(str), conf) //decoder := json.NewDecoder(r) //err = decoder.Decode(conf) if err != nil { log.Error(err.Error()) return false } return true }
//获取微信服务器的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 (token *WeiXinJsApiTicket) Load(appID string) bool { token.AppID = appID err := sqldb.Ormer.Read(token) if err == nil { return true } else if err == orm.ErrNoRows { log.Error("查询不到") return false } else if err == orm.ErrMissPK { log.Error("找不到主键") return false } return false }
//刷新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 LoadJsonURL(url string, conf interface{}) bool { resp, err := http.Get(url) if err != nil { panic(err.Error()) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { panic(err.Error()) } //str = strings.Replace(str, "//", "######", -1) //str = strings.Replace(str, "/", "\\/", -1) //str = strings.Replace(str, "######", "//", -1) err = json.Unmarshal(body, conf) //decoder := json.NewDecoder(r) //err = decoder.Decode(conf) if err != nil { log.Error(err.Error()) return false } return true }
func getCurrentDirectory() string { dir, err := filepath.Abs(filepath.Dir(os.Args[0])) if err != nil { log.Error(err.Error()) } return strings.Replace(dir, "\\", "/", -1) }
func handleStatic(w http.ResponseWriter, r *http.Request) { path := r.URL.Path index := strings.LastIndex(path, ".") if index != -1 { request_type := path[index:] switch request_type { case ".css": w.Header().Set("content-type", "text/css") case ".js": w.Header().Set("content-type", "text/javascript") default: } } path = baseDir + path log.Trace("获取静态文件: %s", path) fin, err := os.Open(path) defer fin.Close() if err != nil { log.Error("static resource: %v", err) w.WriteHeader(505) } else { fd, _ := ioutil.ReadAll(fin) w.Write(fd) } }
func checkWeiXinReturn(retData *WeiXinError) bool { if retData.ErrCode != 0 { log.Error(retData.ErrMsg) return false } return true }
func newWSConn(conn *websocket.Conn, pendingWriteNum int) *WSConn { wsConn := new(WSConn) wsConn.conn = conn wsConn.writeChan = make(chan []byte, pendingWriteNum) go func() { for b := range wsConn.writeChan { if b == nil { break } err := conn.WriteMessage(websocket.BinaryMessage, b) if err != nil { log.Error(err.Error()) break } } conn.Close() wsConn.Lock() wsConn.closeFlag = true wsConn.Unlock() }() return wsConn }
func (g *gateService) StartService(superRpcAddr string) { superClient, err := msg.DialSuperService("tcp", superRpcAddr) maxRetry := 10 for err != nil { if maxRetry > 0 { maxRetry = maxRetry - 1 } else { log.Fatal("连接SuperService失败") return } log.Error("连接SuperService失败,1秒后重试 :%v", err) time.Sleep(time.Second * 1) superClient, err = msg.DialSuperService("tcp", superRpcAddr) } res, err := superClient.Login(&msg.LoginRequst{ServiceIp: proto.String("127.0.0.1")}) if err != nil { log.Fatal("[GATE] 登录SuperService失败 rpc:%s", superRpcAddr) return } g.SuperClient = superClient g.gateway.Addr = string(res.GetServiceIp()) + ":" + strconv.Itoa(int(res.GetExterPort())) g.gateway.HTTPTimeout = 3 * 60 g.gateway.MaxConnNum = 1000 g.gateway.PendingWriteNum = 1000 g.gateway.ProtobufProcessor = g.processor log.Trace("[GATE] 网关服务在%s:%d 启动", string(res.GetServiceIp()), res.GetExterPort()) g.gateway.Run(utils.CloseSig) }
//注册处理redirecturl func RegistAuthRedirectUrl(state string, redirect string) { url, ok := wxProfile.authRedirectAppUrl[state] if ok == true { log.Error(" 重复注册APP:%s的authRedirectAppUrl:%s (已经存在%s)", state, redirect, url) } else { wxProfile.authRedirectAppUrl[state] = redirect } }
//获取主机名 func (s *IdGenerator) hostname() string { name, err := os.Hostname() if err != nil { log.Error("获取主机名失败: %v", err) return "default_host_" } return name }
//构造一个新的id分配器 func NewIdGenerator(workerId, catalogId int64) (*IdGenerator, error) { if workerId > maxWorkerId || workerId < 0 { log.Error("workerId溢出,取值范围[0, %d]", maxWorkerId) return nil, errors.New(fmt.Sprintf("worker Id: %d error", workerId)) } if catalogId > maxCatalogId || catalogId < 0 { log.Error("catalogId溢出,取值范围[0, %d]", maxCatalogId) return nil, errors.New(fmt.Sprintf("catalog Id: %d error", catalogId)) } gid := makeGenID(workerId, catalogId) id, ok := generators[gid] if !ok { id = makeIdGenerator(workerId, catalogId) generators[gid] = id } return id, nil }
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 parseRecvWeiXinMsg(content []byte) *RecvWeiXinMsg { msg := new(RecvWeiXinMsg) err := xml.Unmarshal(content, msg) if err != nil { log.Error(err.Error()) return nil } return msg }
func (a *WSAgent) Run() { a.Trace("run...") msgChan := make(chan []byte, 1024) a.innerMsgChan = make(chan []byte, 1024) a.needClose = make(chan bool) go func() { defer utils.PrintPanicStack() for { if a.conn == nil { a.Error("WSAgent 连接为nil") a.needClose <- true return } data, err := a.conn.ReadMsg() if err != nil { a.Debug("读取消息错误: %v", err) a.needClose <- true return } msgChan <- data } }() for { var data []byte var err error select { case data = <-msgChan: case data = <-a.innerMsgChan: case <-a.needClose: { log.Error("WSAgent 发生错误") a.Close() return } } if a.handlerMessage != nil { _, err = a.handlerMessage(a, data, a.UserData) if err != nil { a.Debug("[handlerMessage]protobuf handle msg error %v", err) //WHY: 解析错误需要跳出循环吗? //break } } else if a.protobufProcessor != nil { _, err = a.protobufProcessor.Handler(a, data, a.UserData) if err != nil { a.Debug("[protobufProcessor]protobuf handle msg error %v", err) //WHY: 解析错误需要跳出循环吗? //break } } } }
func (token *WeiXinJsApiTicket) Save() { var err error if sqldb.Ormer.QueryTable(token).Filter("AppID", token.AppID).Exist() { _, err = sqldb.Ormer.Update(token) } else { _, err = sqldb.Ormer.Insert(token) } if err != nil { log.Error(err.Error()) } else { log.Trace("保存微信AccessToken") } }
func (id *IdGenerator) NextIds(num int) ([]uint64, error) { if num > maxNextIdsNum || num < 0 { log.Error("批量生成ID太多了,范围[0, %d]", maxNextIdsNum) return nil, errors.New(fmt.Sprintf("NextIds num: %d error", num)) } ids := make([]uint64, num) id.mutex.Lock() defer id.mutex.Unlock() var err error for i := 0; i < num; i++ { ids[i], err = id.nextId() if err != nil { return nil, errors.New(fmt.Sprintf("产生单个ID失败,%s,批量生成ID数%d", err.Error(), num)) } } return ids, nil }
func (id *IdGenerator) nextId() (uint64, error) { timestamp := timeGen() if timestamp < id.lastTimestamp { log.Error("IdGenerator分配ID错误,检测到时光倒流 %d 微秒", id.lastTimestamp-timestamp) return 0, errors.New(fmt.Sprintf("IdGenerator分配ID错误,检测到时光倒流 %d 微秒", id.lastTimestamp-timestamp)) } if id.lastTimestamp == timestamp { id.sequence = (id.sequence + 1) & sequenceMask if id.sequence == 0 { timestamp = tilNextMillis(id.lastTimestamp) } } else { id.sequence = 0 } id.lastTimestamp = timestamp return uint64(((timestamp - id.twepoch) << timestampLeftShift) | (id.catalogId << catalogIdShift) | (id.workerId << workerIdShift) | id.sequence), nil }
func serverStub() { transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory()) protocolFactory := thrift.NewTBinaryProtocolFactoryDefault() //protocolFactory := thrift.NewTCompactProtocolFactory() serverTransport, err := thrift.NewTServerSocket(NetworkAddr) if err != nil { log.Error("Error!", err) return } handler := &RpcServiceImpl{} processor := demo.NewRpcServiceProcessor(handler) server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) log.Trace("thrift server in", NetworkAddr) server.Serve() }
//绑定端口,等待连接 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 main() { nosql.InitRedis(global.RedisURL, global.RedisPin, 0) sqldb.Init() mux := http.NewServeMux() weixin.InitWeiXin(&weixin.WeiXinConfig{AppID: global.AppID, AppSecret: global.AppSecret, OwnerID: global.OwnerID, ProcessMsg: nil, UserAuthorized: UserAuthorized, ServiceToken: "test_wx", MyServiceDomain: global.ServiceDomain, AuthRedirectURL: "http://" + global.ServiceDomain + "/wx/authorize_redirect"}, mux) weixin.RegistAuthRedirectUrl("FIRST_TEST", "http://"+global.ServiceDomain+"/app/demo") mux.HandleFunc("/htdoc/", handleStatic) mux.HandleFunc("/app/demo", handleAppDemo) mux.HandleFunc("/wx/api/", handleWxApi) if err := http.ListenAndServe(":3000", mux); err != nil { log.Error(err.Error()) } //if err := http.ListenAndServeTLS(":3000", baseDir+"https/cert.pem", baseDir+"https/key.pem", mux); err != nil { // log.Error(err.Error()) //} return log.Trace("启动......") go superservice.Instance.StartService(utils.SuperRpcAddr) go gateservice.Instance.StartService(utils.SuperRpcAddr) <-utils.CloseSig log.Trace("结束......") return test.TestSinaAuth() auth.InitAuthHttpService() test.TestProtorpc() utils.TestSnow() }
func queryAccount(stms *sql.Stmt, key string) *msg.OAtuhUserProfile { rows, err := stms.Query(key) if err != nil { log.Error(err.Error()) return nil } data := &msg.OAtuhUserProfile{} found := 0 for rows.Next() { found++ var accid uint64 var nake_name string var token string err = rows.Scan(&accid, &nake_name, &token) data.Accid = proto.Uint64(accid) data.Name = proto.String(nake_name) data.Oauth = proto.String("SELF") } if found == 1 { return data } else { return nil } }
func (a *TCPAgent) Error(format string, d ...interface{}) { log.Error(a.description()+format, d...) }
func TestMysql() { db, err := sql.Open("mysql", global.MySqlUrl) if err != nil { log.Error(err.Error()) } err = db.Ping() if err != nil { log.Error(err.Error()) } rows, err := db.Query("select ACCID,NAKE_NAME from ACCOUNT") if err != nil { log.Error(err.Error()) } stmtIns, err := db.Prepare("insert into ACCOUNT (`ACCID`,`NAKE_NAME`) values( ?, ? )") if err != nil { log.Error(err.Error()) } var result sql.Result result, err = stmtIns.Exec("666", "去") if err != nil { log.Error(err.Error()) } else { n, _ := result.RowsAffected() log.Trace("影响的行数 %d", n) } stmtDel, err := db.Prepare("delete from `ACCOUNT` where `ACCID`=?") if err != nil { log.Error(err.Error()) } stmtDel.Exec(666) defer rows.Close() for rows.Next() { var accid uint64 var nake_name string err = rows.Scan(&accid, &nake_name) if err != nil { log.Error(err.Error()) } log.Trace("找到数据 %d, %s", accid, nake_name) } //// findToken, err := db.Prepare("select `ACCID`, `NAKE_NAME`,`TOKEN` from `ACCOUNT` where `TOKEN`=?") if err != nil { log.Error(err.Error()) } rows, err = findToken.Query("EEE") findSina, err := db.Prepare("select `ACCID`, `NAKE_NAME`,`TOKEN` from `ACCOUNT` where `SINA_UID`=?") rows, err = findSina.Query(1) log.Trace("=========================") if err != nil { log.Error(err.Error()) } for rows.Next() { var accid uint64 var nake_name string var token string err = rows.Scan(&accid, &nake_name, &token) if err != nil { log.Error(err.Error()) } log.Trace("TOKEN找到数据 accis:%d, nake_name:%s token:%s", accid, nake_name, token) } }
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 InitAuthService(supply IAuthSupply, http_service *AuthHttpService) *AuthService { if http_service == nil { log.Error("AuthHttpService没有初始化, 调用InitAuthHttpService函数初始化") return nil } else { service := new(AuthService) service = new(AuthService) service.callback = make(map[uint64]AuthCallBackFunc) service.oauthCfg = &oauth2.Config{ ClientID: supply.GetClientID(), ClientSecret: supply.GetClientSecret(), Endpoint: supply.GetEndPoint(), RedirectURL: AuthServiceUrl + supply.GetRedirectURL(), Scopes: nil, } http_service.mux.HandleFunc(supply.GetRedirectURL(), func(w http.ResponseWriter, r *http.Request) { data := new(AuthUserData) data.Response = w data.Request = r data.ServiceName = "sina" log.Trace("OAuth2接口授权返回: " + r.RequestURI + "来自" + r.RemoteAddr) code := r.FormValue("code") state, err := strconv.ParseInt(r.FormValue("state"), 10, 64) if err != nil { log.Error("OAuth2接口授权返回accid错误") return } accid := uint64(state) defer delete(service.callback, accid) cb, ok := service.callback[uint64(accid)] if !ok { log.Error("没有找到授权回调函数: " + strconv.FormatUint(accid, 10)) return } var ( ctx context.Context cancel context.CancelFunc ) ctx, cancel = context.WithCancel(context.Background()) defer cancel() token, err := service.oauthCfg.Exchange(ctx, code) if err != nil { log.Error(err.Error()) cb(nil, accid, err) } else { req, err := service.oauthCfg.Client(ctx, token).Get(supply.GetProfileInfoURL(token)) if err != nil { log.Error("OAuth2接口获取用户信息错误:%s accid:%d", err.Error(), accid) cb(nil, accid, err) } else { body, _ := ioutil.ReadAll(io.LimitReader(req.Body, 1<<20)) data.Accid = accid data.AcessToken = token.AccessToken data.Raw = string(body) if err := supply.ParseAuthUserData(data, body); err == nil { cb(data, accid, nil) } else { cb(nil, accid, err) } } } }) return service } }
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)) } } }