|
- package main
-
- import (
- "crypto/sha1"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "net/http"
- "net/http/httputil"
- "net/url"
- "os"
- "sort"
- "strings"
- )
-
- //apiV1Main version 1 main entry for all wechat callbacks
- //
- func apiV1Main(w http.ResponseWriter, r *http.Request) {
- logRequestDebug(httputil.DumpRequest(r, true))
- if checkSignature(r) == false {
- log.Println("signature of URL incorrect")
- w.Header().Set("Content-Type", "text/xml; charset=utf-8")
- w.WriteHeader(http.StatusUnauthorized)
- fmt.Fprintf(w, "") //empty string
- return
- }
-
- switch r.Method {
- case "POST":
- //answerWechatPostEcho(w, r)
- answerWechatPost(w, r)
- case "GET":
- answerInitialAuth(w, r)
- default:
- log.Fatalln(fmt.Sprintf("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) {
- body, _ := ioutil.ReadAll(r.Body)
- d := decryptToXML(string(body))
- fmt.Printf("decrypt as: %s\n", d)
- h := ReadCommonHeader(d)
- reply, _ := BuildTextMsg(h.MsgType, h.FromUserName)
- if h.MsgType == "text" {
- reply, _ = BuildTextMsg("http://www.hitxy.org.au/", h.FromUserName)
- }
- if h.MsgType == "voice" {
- a := ReadVoiceMsg(d)
- reply, _ = BuildTextMsg(a.Recognition, h.FromUserName)
- }
- if h.MsgType == "event" {
- a := ReadEventMsg(d)
- if a.Event == "LOCATION" {
- reply = BuildLocationMsg(0, 0, 0, h.FromUserName)
- fmt.Printf("output %s", reply)
- } else {
- reply, _ = BuildTextMsg(a.Event+"/"+a.EventKey, h.FromUserName)
- }
- //mediaID := "cU8BYvAEp3H25V-yGO3WBtMVk2bZcEBgf_kje7V-EPkRA_U4x-OAWb_ONg6Y-Qxt" //video
- //mediaID := "e2iNEiSxCX5TV1WbFd0TQPTdMx8WbvpkOs_iNhSVQHY" // 236 second mp3
- //mediaID := "e2iNEiSxCX5TV1WbFd0TQDVyk970GxTcBWMnqc2RzF0" //5 sec mp3
- //mediaID := "e2iNEiSxCX5TV1WbFd0TQMqvVrqFDbDOacdjgQ-OAuE" //news
- //reply = buildVideoMsg(h.FromUserName, mediaID, "标题", a.Event+"/"+a.EventKey)
-
- //reply = buildUploadPicMsg(h.FromUserName, "media_for_test/640x480.jpg")
- //reply = buildUploadVoiceMsg(h.FromUserName, "media_for_test/music.mp3")
- //reply = buildVoiceMsg(h.FromUserName, mediaID)
- reply = buildSampleMusicMsg(h.FromUserName)
- //reply = buildSampleArticleMsg(h.FromUserName)
- }
- w.Header().Set("Content-Type", "text/xml; charset=utf-8")
- fmt.Fprint(w, reply)
- return
- }
-
- func answerWechatPostEcho(w http.ResponseWriter, r *http.Request) {
- body, _ := ioutil.ReadAll(r.Body)
- //fmt.Printf("get body: %s", string(body))
- s := ReadEncryptedMsg(string(body))
- //fmt.Printf("to decrypt %s", s.Encrypt)
- d := Decode(s.Encrypt)
- fmt.Printf("echo as: \n%s", d)
-
- e := strings.Replace(d, "ToUserName", "FDDD20170506xyzunique", 2)
- f := strings.Replace(e, "FromUserName", "ToUserName", 2)
- g := strings.Replace(f, "FDDD20170506xyzunique", "FromUserName", 2)
- fmt.Fprint(w, g)
- }
-
- //
- func checkSignature(r *http.Request) bool {
- rq := r.URL.RawQuery
- m, _ := url.ParseQuery(rq)
-
- signature, sok := m["signature"]
- timestamp, tok := m["timestamp"]
- nonce, nok := m["nonce"]
- token := APIConfig.Token
- if sok && tok && nok {
- //sort token, timestamp, nonce and join them
- strs := []string{token, timestamp[0], nonce[0]}
- sort.Strings(strs)
- s := strings.Join(strs, "")
-
- //calculate sha1
- h := sha1.New()
- h.Write([]byte(s))
- calculated := fmt.Sprintf("%x", h.Sum(nil))
- return signature[0] == calculated
- }
- 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 "/"
- // essentially to prove the webserver is still alive
- // echo query string to the client
- func webrootHandler(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
- rq := r.URL.RawQuery
- m, _ := url.ParseQuery(rq)
- for index, element := range m {
- fmt.Fprintf(w, "\n%s => %s", index, element)
- }
- logRequestDebug(httputil.DumpRequest(r, true))
-
- }
-
- func logRequestDebug(data []byte, err error) {
- if err == nil {
- fmt.Printf("%s\n\n", string(data))
- } else {
- log.Fatalf("%s\n\n", err)
- }
- }
-
- //save uploaded 'file' into temporary location
- func uploadHandler(w http.ResponseWriter, r *http.Request) {
- r.ParseMultipartForm(32 << 20) //32MB memory
- file, handler, err := r.FormFile("file") //form-field 'file'
- if err != nil {
- fmt.Println(err)
- return
- }
- defer file.Close()
- fmt.Fprintf(w, "%v", handler.Header)
- f, err := os.OpenFile("/tmp/wechat_hitxy_"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
- if err != nil {
- fmt.Println(err)
- return
- }
- defer f.Close()
- io.Copy(f, file)
- }
-
- func crmAttachmentHandler(w http.Response, r *http.Request) {
- http.ServeFile(w, r)
- }
|