Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

127 lines
2.7KB

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