Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

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