diff --git a/Api_request.txt b/Api_request.txt
index 879f337..44b74bd 100644
--- a/Api_request.txt
+++ b/Api_request.txt
@@ -1,3 +1,18 @@
+Initial auth URL
+
+GET /api?signature=e39de9f2e28079c01ebb4b803dfc3442b819545c&echostr=913461463450840893×tamp=1492970761&nonce=1850971833 HTTP/1.1
+Host: wechat.hitxy.org.au
+Accept: */*
+Cache-Control: no-cache
+Connection: Keep-Alive
+Pragma: no-cache
+User-Agent: Mozilla/4.0
+X-Forwarded-For: 103.7.30.107
+X-Forwarded-Host: wechat.hitxy.org.au
+X-Forwarded-Server: wechat.hitxy.org.au
+
+
+
Unfollow:
POST /api?signature=ed32de69a7977a8468ca72fa45125a6506cc2cde×tamp=1492790658&nonce=644867704&openid=oUN420bxqFqlx0ZQHciUOesZO3PE&encrypt_type=aes&msg_signature=00db32d3a36e80969c65d6ff94d85b73dfdede43 HTTP/1.1
@@ -170,4 +185,30 @@ X-Forwarded-Server: wechat.hitxy.org.au
+
+
+
+receive TxtMessage
+
+POST /api?signature=847523ccbd3d6db7ed77b78a89f4019a109bde82×tamp=1492829058&nonce=1739586053&openid=oUN420bxqFqlx0ZQHciUOesZO3PE&encrypt_type=aes&msg_signature=8fa8be1428e6ee3d8a3332213e00bec019821677 HTTP/1.1
+Host: wechat.hitxy.org.au
+Accept: */*
+Cache-Control: no-cache
+Connection: Keep-Alive
+Content-Length: 771
+Content-Type: text/xml
+Pragma: no-cache
+User-Agent: Mozilla/4.0
+X-Forwarded-For: 103.7.30.105
+X-Forwarded-Host: wechat.hitxy.org.au
+X-Forwarded-Server: wechat.hitxy.org.au
+
+
+
+
+ 1492829058
+
+
+ 6411651983041024410
+
\ No newline at end of file
diff --git a/config.go b/config.go
new file mode 100644
index 0000000..537f92c
--- /dev/null
+++ b/config.go
@@ -0,0 +1,35 @@
+package main
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "log"
+)
+
+//WechatAPIConfig all secret related API Config
+type WechatAPIConfig struct {
+ //Token is the wechat API shared secrete
+ Token string `json:"Token"`
+
+ //EncodingAESKey is the Key for encrypt messages
+ EncodingAESKey string `'json:"EncodingAESKey"`
+
+ //Appid is wechat public account appid
+ Appid string `json:"Appid"`
+
+ //AppSecret is how we identify ourselves.
+ AppSecret string `json:"AppSecret"`
+}
+
+//APIConfig contains secrets that cannot store in source file
+var APIConfig WechatAPIConfig
+
+func readConfig() error {
+
+ log.Printf("read config from %s\r\n", "server_config.json")
+ body, err := ioutil.ReadFile("server_config.json")
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(body, &APIConfig)
+}
diff --git a/main.go b/main.go
index 99fea28..6cc9fb7 100644
--- a/main.go
+++ b/main.go
@@ -1,18 +1,27 @@
package main
import (
+ "crypto/sha1"
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
+ "sort"
+ "strings"
)
func main() {
+ if readConfig() != nil {
+ log.Fatal("unable to read config, program quit")
+ return
+ }
+ //setup handler
http.HandleFunc("/", webrootHandler)
http.HandleFunc("/api", apiV1Main)
+
//http.ListenAndServe("127.0.0.1:65500", nil)
- CreateDefaultMenu()
+ //CreateDefaultMenu()
http.ListenAndServe(":65500", nil)
}
@@ -20,9 +29,77 @@ func main() {
//
func apiV1Main(w http.ResponseWriter, r *http.Request) {
logRequestDebug(httputil.DumpRequest(r, true))
+
+ switch r.Method {
+ case "POST":
+ answerWechatPost(w, r)
+ case "GET":
+ answerInitialAuth(w, r)
+ default:
+ log.Fatalln("Unhandled HTTP %s", r.Method)
+ fmt.Fprintf(w, "Protocol Error: Expect GET or POST only")
+ }
+}
+
+//
+//answerInitialAuth, when wechat first verify our URL for API hooks
+//
+func answerInitialAuth(w http.ResponseWriter, r *http.Request) {
+ rq := r.URL.RawQuery
+ m, _ := url.ParseQuery(rq)
+
+ echostr, eok := m["echostr"]
+ if checkSignature(r) && eok {
+ fmt.Fprintf(w, echostr[0])
+ } else {
+ fmt.Fprintf(w, "wtf is wrong with the Internet")
+ }
+}
+
+//answerWechatPost distribute PostRequest according to xml body info
+//
+func answerWechatPost(w http.ResponseWriter, r *http.Request) {
+ return
+}
+
+//
+func checkSignature(r *http.Request) bool {
rq := r.URL.RawQuery
m, _ := url.ParseQuery(rq)
- fmt.Fprintf(w, m["echostr"][0])
+
+ signature, sok := m["signature"]
+ timestamp, tok := m["timestamp"]
+ nonce, nok := m["nonce"]
+ token := APIConfig.Token
+ if sok && tok && nok {
+
+ strs := []string{token, timestamp[0], nonce[0]}
+
+ sort.Strings(strs)
+ s := strings.Join(strs, "")
+
+ h := sha1.New()
+ h.Write([]byte(s))
+ us := fmt.Sprintf("%x", h.Sum(nil))
+ return signature[0] == us
+ }
+ return false
+}
+
+func checkSignature1() bool {
+ s1 := "e39de9f2e28079c01ebb4b803dfc3442b819545c"
+ t1 := "1492970761"
+ n1 := "1850971833"
+ token := APIConfig.Token
+
+ strs := []string{token, t1, n1}
+ sort.Strings(strs)
+ s := strings.Join(strs, "")
+
+ h := sha1.New()
+ h.Write([]byte(s))
+ us := fmt.Sprintf("%x", h.Sum(nil))
+ return s1 == us
}
//webrootHandler sending contents to client when request "/"
diff --git a/server_config.json b/server_config.json
new file mode 100644
index 0000000..9678c1d
--- /dev/null
+++ b/server_config.json
@@ -0,0 +1,6 @@
+{
+ "Token": "skdq8vklaurfqemfszuif",
+ "EncodingAESKey": "cmtWK2teRnLOXyO5dw7lJkETv9jCeNAqYyguEu5D8gG",
+ "Appid": "wx876e233fde456b7b",
+ "AppSecret": "4a91aa328569b10a9fb97adeb8b0af58"
+}
\ No newline at end of file