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

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