You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 satır
2.6KB

  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. strs := []string{token, timestamp[0], nonce[0]}
  66. sort.Strings(strs)
  67. s := strings.Join(strs, "")
  68. h := sha1.New()
  69. h.Write([]byte(s))
  70. us := fmt.Sprintf("%x", h.Sum(nil))
  71. return signature[0] == us
  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, "\r\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. }