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

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