No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

122 líneas
2.7KB

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