Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

127 Zeilen
2.9KB

  1. package main
  2. import (
  3. "crypto/sha1"
  4. "fmt"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "net/http/httputil"
  9. "net/url"
  10. "sort"
  11. "strings"
  12. )
  13. //apiV1Main version 1 main entry for all wechat callbacks
  14. //
  15. func apiV1Main(w http.ResponseWriter, r *http.Request) {
  16. logRequestDebug(httputil.DumpRequest(r, true))
  17. if checkSignature(r) == false {
  18. log.Println("signature of URL incorrect")
  19. fmt.Fprintf(w, "") //empty string
  20. return
  21. }
  22. switch r.Method {
  23. case "POST":
  24. answerWechatPost(w, r)
  25. case "GET":
  26. answerInitialAuth(w, r)
  27. default:
  28. log.Fatalln(fmt.Sprintf("Unhandled HTTP %s", r.Method))
  29. fmt.Fprintf(w, "Protocol Error: Expect GET or POST only")
  30. }
  31. }
  32. //
  33. //answerInitialAuth, when wechat first verify our URL for API hooks
  34. //
  35. func answerInitialAuth(w http.ResponseWriter, r *http.Request) {
  36. rq := r.URL.RawQuery
  37. m, _ := url.ParseQuery(rq)
  38. echostr, eok := m["echostr"]
  39. if checkSignature(r) && eok {
  40. fmt.Fprintf(w, echostr[0])
  41. } else {
  42. fmt.Fprintf(w, "wtf is wrong with the Internet")
  43. }
  44. }
  45. //answerWechatPost distribute PostRequest according to xml body info
  46. //
  47. func answerWechatPost(w http.ResponseWriter, r *http.Request) {
  48. body, _ := ioutil.ReadAll(r.Body)
  49. fmt.Printf("get body: %s", string(body))
  50. s := ReadEncryptedMsg(string(body))
  51. //fmt.Printf("to decrypt %s", s.Encrypt)
  52. d := Decode(s.Encrypt)
  53. fmt.Printf("decrypt as: %s", d)
  54. h := ReadCommonHeader(d)
  55. reply, _ := BuildTextMsg(h.MsgType, h.FromUserName)
  56. fmt.Fprint(w, reply)
  57. return
  58. }
  59. //
  60. func checkSignature(r *http.Request) bool {
  61. rq := r.URL.RawQuery
  62. m, _ := url.ParseQuery(rq)
  63. signature, sok := m["signature"]
  64. timestamp, tok := m["timestamp"]
  65. nonce, nok := m["nonce"]
  66. token := APIConfig.Token
  67. if sok && tok && nok {
  68. //sort token, timestamp, nonce and join them
  69. strs := []string{token, timestamp[0], nonce[0]}
  70. sort.Strings(strs)
  71. s := strings.Join(strs, "")
  72. //calculate sha1
  73. h := sha1.New()
  74. h.Write([]byte(s))
  75. calculated := fmt.Sprintf("%x", h.Sum(nil))
  76. return signature[0] == calculated
  77. }
  78. return false
  79. }
  80. func checkSignature1() bool {
  81. s1 := "e39de9f2e28079c01ebb4b803dfc3442b819545c"
  82. t1 := "1492970761"
  83. n1 := "1850971833"
  84. token := APIConfig.Token
  85. strs := []string{token, t1, n1}
  86. sort.Strings(strs)
  87. s := strings.Join(strs, "")
  88. h := sha1.New()
  89. h.Write([]byte(s))
  90. us := fmt.Sprintf("%x", h.Sum(nil))
  91. return s1 == us
  92. }
  93. //webrootHandler sending contents to client when request "/"
  94. // essentially to prove the webserver is still alive
  95. // echo query string to the client
  96. func webrootHandler(w http.ResponseWriter, r *http.Request) {
  97. fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
  98. rq := r.URL.RawQuery
  99. m, _ := url.ParseQuery(rq)
  100. for index, element := range m {
  101. fmt.Fprintf(w, "\n%s => %s", index, element)
  102. }
  103. logRequestDebug(httputil.DumpRequest(r, true))
  104. }
  105. func logRequestDebug(data []byte, err error) {
  106. if err == nil {
  107. fmt.Printf("%s\n\n", data)
  108. } else {
  109. log.Fatalf("%s\n\n", err)
  110. }
  111. }