Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

211 lines
6.0KB

  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "log"
  6. "net/http"
  7. "net/http/httputil"
  8. "net/url"
  9. "os"
  10. "strconv"
  11. "strings"
  12. "time"
  13. )
  14. //PathsConfig all system available pathes
  15. type PathsConfig struct {
  16. Angular2App string `json:"angular2_app"`
  17. SinglePageEdit string `json:"singlePageEdit"`
  18. }
  19. //GlobalPath all global pathes configurations
  20. // TODO: setup GlobalPath Config, from reading file
  21. var GlobalPath = PathsConfig{
  22. "dist/",
  23. "spa/",
  24. }
  25. //KFUsers info cache about current customer service
  26. var KFUsers kfCache
  27. func main() {
  28. err := readConfig() //wechat API config
  29. if err != nil {
  30. log.Println(err)
  31. log.Fatal("unable to read server_config.json, program quit")
  32. return
  33. }
  34. err = readCRMConfig()
  35. if err != nil {
  36. log.Println(err)
  37. log.Fatal("unable to read crm_config.json, program quit")
  38. }
  39. err = IntraAPIConfig.readConfig()
  40. if err != nil {
  41. log.Println(err)
  42. log.Fatal("unable to read intra-api-config, program quit")
  43. }
  44. initAllProc()
  45. setupRootFileServer()
  46. startSessionManager(2048)
  47. KFUsers.kfRenewList()
  48. //always the last one
  49. setupHTTPHandler()
  50. }
  51. func setupHTTPHandler() {
  52. //setup handler
  53. //http.HandleFunc("/", webrootHandler)
  54. http.HandleFunc("/api", apiV1Main)
  55. http.HandleFunc("/upload", uploadHandler)
  56. http.HandleFunc("/crmfiles/", crmAttachmentHandler)
  57. http.HandleFunc("/dumprequest", dumpReuestHandler)
  58. http.HandleFunc("/MP_verify_6JqVkftKr39GMakA.txt", mpDomainAuthSecret)
  59. http.HandleFunc("/redirect", setTrackingCookieAndRecirect)
  60. http.HandleFunc("/iapi/getAccessToken", supplyAccessToken)
  61. http.HandleFunc("/iapi/createWechatQr", iapiCreateWechatQrCode)
  62. http.HandleFunc("/crmpixel.png", crmpixel) //tracking pixel.
  63. http.HandleFunc("/crmcache", crmcache)
  64. http.HandleFunc("/spa/editprofile", spaEditProfile)
  65. http.ListenAndServe(":65500", nil)
  66. }
  67. func startSessionManager(concurrent int) {
  68. m := SessionManager{}
  69. AllInMessage = make(chan *InWechatMsg, concurrent)
  70. go m.startSessionManager(AllInMessage)
  71. }
  72. func setupRootFileServer() {
  73. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  74. http.ServeFile(w, r, GlobalPath.Angular2App+r.URL.Path[1:])
  75. })
  76. fs := http.FileServer(http.Dir(GlobalPath.SinglePageEdit))
  77. http.Handle("/spa/", http.StripPrefix("/spa", fs))
  78. //fs := http.FileServer(http.Dir("/mnt/data/workspace/angular.ts/wechat/ng2-admin/dist"))
  79. //http.Handle("/", fs)
  80. }
  81. func dumpReuestHandler(w http.ResponseWriter, r *http.Request) {
  82. logRequestDebug(httputil.DumpRequest(r, true))
  83. w.Header().Set("Content-Type", "application/json; charset=utf-8")
  84. w.Header().Set("Access-Control-Allow-Origin", "http://192.168.1.39:4200")
  85. w.Header().Set("Access-Control-Allow-Headers", "Authorziation11,Authorziation12")
  86. w.Header().Set("Access-Control-Allow-Credentials", "true")
  87. w.Header().Set("Access-Control-Expose-Headers", "Set-Cookie,myheader,*")
  88. w.Header().Set("myheader", "myheader-data")
  89. // expiration := time.Now().Add(10 * 365 * 24 * time.Hour)
  90. // str := time.Now().String()
  91. // cookie := http.Cookie{Name: "username", Value: str, Expires: expiration}
  92. // http.SetCookie(w, &cookie)
  93. fmt.Fprintf(w, `{"status":"OK"}`)
  94. for _, c := range r.Cookies() {
  95. log.Println(c.Name)
  96. log.Println(c.Value)
  97. }
  98. err := r.ParseMultipartForm(32 << 20)
  99. if err == nil {
  100. for k, v := range r.Form {
  101. fmt.Println("key:", k)
  102. fmt.Println("val:", strings.Join(v, ""))
  103. }
  104. file, handler, err := r.FormFile("avatar")
  105. if err == nil {
  106. defer file.Close()
  107. log.Printf("%v", handler.Header)
  108. log.Println(handler.Filename)
  109. f, err := os.OpenFile("/tmp/wechat_hitxy_avatar_upload.jpg", os.O_WRONLY|os.O_CREATE, 0666)
  110. if err != nil {
  111. fmt.Println(err)
  112. return
  113. }
  114. defer f.Close()
  115. io.Copy(f, file)
  116. }
  117. } else {
  118. log.Print(err)
  119. }
  120. }
  121. func supplyAccessToken(w http.ResponseWriter, r *http.Request) {
  122. //logRequestDebug(httputil.DumpRequest(r, true))
  123. if checkSignatureByToken(r, IntraAPIConfig.CRMSecrete) {
  124. atk, _ := GetAccessToken()
  125. fmt.Fprint(w, atk)
  126. } else {
  127. w.WriteHeader(401)
  128. fmt.Fprint(w, "unauthorized")
  129. }
  130. }
  131. func iapiCreateWechatQrCode(w http.ResponseWriter, r *http.Request) {
  132. logRequestDebug(httputil.DumpRequest(r, true))
  133. if !checkSignatureByToken(r, IntraAPIConfig.CRMSecrete) {
  134. w.WriteHeader(http.StatusUnauthorized)
  135. fmt.Fprint(w, "unauthorized")
  136. return
  137. }
  138. rq := r.URL.RawQuery
  139. m, _ := url.ParseQuery(rq)
  140. qrValue, qok := m["qrValue"]
  141. expire, eok := m["expire"]
  142. if !qok || !eok {
  143. w.WriteHeader(http.StatusUnprocessableEntity)
  144. fmt.Fprintf(w, "parameter not correct, bad api call %s", time.Now().Format(getCrmTimeLayout()))
  145. return
  146. }
  147. if isStrInt(qrValue[0]) && isStrInt(expire[0]) {
  148. intVal, _ := strconv.Atoi(qrValue[0])
  149. intExpire, _ := strconv.Atoi(expire[0])
  150. jsonB, err := iapiCreateTempQr(int32(intVal), int32(intExpire))
  151. if err == nil {
  152. w.Write(jsonB)
  153. } else {
  154. fmt.Fprintf(w, "%s", err)
  155. }
  156. return
  157. }
  158. if !isStrInt(qrValue[0]) && expire[0] == "0" {
  159. jsonB, err := isapiCreatePermQr(qrValue[0])
  160. if err == nil {
  161. w.Write(jsonB)
  162. } else {
  163. fmt.Fprintf(w, "%s", err)
  164. }
  165. return
  166. }
  167. }
  168. func isStrInt(v string) bool {
  169. if _, err := strconv.Atoi(v); err == nil {
  170. return true
  171. }
  172. return false
  173. }
  174. // 用户在网页授权页同意授权给公众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以确保安全可靠。
  175. // 注意事项:
  176. // 1、回调页面域名或路径需使用字母、数字及“-”的组合(例:wx.qq.com或wx.qq.com/mp),不支持IP地址、端口号及短链域名。填写的域名或路径需与实际回调URL中的域名或路径相同。
  177. // 2、填写的域名须通过ICP备案的验证。
  178. // 3、将文件MP_verify_6JqVkftKr39GMakA.txt(点击下载)上传至填写域名或路径指向的web服务器(或虚拟主机)的目录(若填写域名,将文件放置在域名根目录下,例如wx.qq.com/MP_verify_6JqVkftKr39GMakA.txt;若填写路径,将文件放置在路径目录下,例如wx.qq.com/mp/MP_verify_6JqVkftKr39GMakA.txt),并确保可以访问。
  179. func mpDomainAuthSecret(w http.ResponseWriter, r *http.Request) {
  180. fmt.Fprintf(w, "6JqVkftKr39GMakA")
  181. //由于需要什么ICP备案,这个功能不能使用
  182. }