wxapi.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. package wxapi
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "io/ioutil"
  8. "net/http"
  9. "strings"
  10. "sync"
  11. "time"
  12. )
  13. const (
  14. GetTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET"
  15. GetServiceUrl = "https://qyapi.weixin.qq.com/cgi-bin/kf/account/list?access_token=ACCESS_TOKEN"
  16. GetServicerUrl = "https://qyapi.weixin.qq.com/cgi-bin/kf/servicer/list?access_token=ACCESS_TOKEN&open_kfid=OPEN_KFID"
  17. GetStaffUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&userid=USERID"
  18. GetCustomerUrl = "https://qyapi.weixin.qq.com/cgi-bin/kf/customer/batchget?access_token=ACCESS_TOKEN"
  19. GetMsgUrl = "https://qyapi.weixin.qq.com/cgi-bin/kf/sync_msg?access_token=ACCESS_TOKEN"
  20. )
  21. // 自定义封装企业微信的API接口
  22. type WxApi struct {
  23. lock sync.Mutex
  24. corpid string
  25. corpsecret string
  26. accessToken string
  27. tokenExpiresTime int64
  28. expiresIn int64
  29. }
  30. func NewWxApi(corpid, corpsecret string) *WxApi {
  31. return &WxApi{corpid: corpid, corpsecret: corpsecret}
  32. }
  33. // 刷新token
  34. func (a *WxApi) refreshAccessToken() error {
  35. if a.accessToken == "" || (a.tokenExpiresTime-time.Now().Unix()) < (a.expiresIn/10) {
  36. a.lock.Lock()
  37. defer a.lock.Unlock()
  38. if !((a.tokenExpiresTime - time.Now().Unix()) < (a.expiresIn / 10)) {
  39. return nil
  40. }
  41. url := GetTokenUrl
  42. url = strings.ReplaceAll(url, "ID", a.corpid)
  43. url = strings.ReplaceAll(url, "SECRET", a.corpsecret)
  44. resp, err := http.Get(url)
  45. if err != nil {
  46. return err
  47. }
  48. defer resp.Body.Close()
  49. bts, err := ioutil.ReadAll(resp.Body)
  50. if err != nil {
  51. return err
  52. }
  53. var data TokenResp
  54. err = json.Unmarshal(bts, &data)
  55. if err != nil {
  56. return err
  57. }
  58. if data.Errcode != 0 {
  59. return errors.New(fmt.Sprintf("errcode: %v,errmsg: %v", data.Errcode, data.Errmsg))
  60. }
  61. a.accessToken = data.AccessToken
  62. a.expiresIn = data.ExpiresIn
  63. a.tokenExpiresTime = time.Now().Add(time.Duration(data.ExpiresIn) * time.Second).Unix()
  64. }
  65. return nil
  66. }
  67. // GetServiceList 获取客服账号列表
  68. func (a *WxApi) GetServiceList() (err error, list []ServiceAccount) {
  69. err = a.refreshAccessToken()
  70. if err != nil {
  71. return
  72. }
  73. url := GetServiceUrl
  74. url = strings.ReplaceAll(url, "ACCESS_TOKEN", a.accessToken)
  75. res, err := http.Post(url, "application/json", strings.NewReader(`{"offset":0,"limit":999}`))
  76. if err != nil {
  77. return
  78. }
  79. defer res.Body.Close()
  80. bodyBts, err := ioutil.ReadAll(res.Body)
  81. if err != nil {
  82. return
  83. }
  84. var data ServiceListResp
  85. err = json.Unmarshal(bodyBts, &data)
  86. if err != nil {
  87. return
  88. }
  89. if data.Errcode != 0 {
  90. return errors.New(fmt.Sprintf("errcode: %v,errmsg: %v", data.Errcode, data.Errmsg)), nil
  91. }
  92. list = data.AccountList
  93. return
  94. }
  95. // GetServicerList 获取接待账号列表
  96. func (a *WxApi) GetServicerList(openKfid string) (err error, list []ServicerAccount) {
  97. err = a.refreshAccessToken()
  98. if err != nil {
  99. return
  100. }
  101. url := GetServicerUrl
  102. url = strings.ReplaceAll(url, "ACCESS_TOKEN", a.accessToken)
  103. url = strings.ReplaceAll(url, "OPEN_KFID", openKfid)
  104. res, err := http.Get(url)
  105. if err != nil {
  106. return
  107. }
  108. defer res.Body.Close()
  109. bodyBts, err := ioutil.ReadAll(res.Body)
  110. if err != nil {
  111. return
  112. }
  113. var data ServicerListResp
  114. err = json.Unmarshal(bodyBts, &data)
  115. if err != nil {
  116. return
  117. }
  118. if data.Errcode != 0 {
  119. return errors.New(fmt.Sprintf("errcode: %v,errmsg: %v", data.Errcode, data.Errmsg)), nil
  120. }
  121. list = data.ServicerList
  122. return
  123. }
  124. // 读取成员
  125. func (a *WxApi) GetStaffList(userid string) (err error, d Staff) {
  126. err = a.refreshAccessToken()
  127. if err != nil {
  128. return
  129. }
  130. url := GetStaffUrl
  131. url = strings.ReplaceAll(url, "ACCESS_TOKEN", a.accessToken)
  132. url = strings.ReplaceAll(url, "USERID", userid)
  133. res, err := http.Get(url)
  134. if err != nil {
  135. return
  136. }
  137. defer res.Body.Close()
  138. bodyBts, err := ioutil.ReadAll(res.Body)
  139. if err != nil {
  140. return
  141. }
  142. var data StaffResp
  143. err = json.Unmarshal(bodyBts, &data)
  144. if err != nil {
  145. return
  146. }
  147. if data.Errcode != 0 {
  148. return errors.New(fmt.Sprintf("errcode: %v,errmsg: %v", data.Errcode, data.Errmsg)), Staff{}
  149. }
  150. d = data.Staff
  151. return
  152. }
  153. // GetCustomerList 获取客户基础信息列表
  154. func (a *WxApi) GetCustomerList(userIds []string) (err error, list []Customer) {
  155. err = a.refreshAccessToken()
  156. if err != nil {
  157. return
  158. }
  159. url := GetCustomerUrl
  160. url = strings.ReplaceAll(url, "ACCESS_TOKEN", a.accessToken)
  161. body := CustomerParam{
  162. ExternalUseridList: userIds,
  163. NeedEnterSessionContext: 0,
  164. }
  165. bts, _ := json.Marshal(body)
  166. res, err := http.Post(url, "application/json", bytes.NewReader(bts))
  167. if err != nil {
  168. return
  169. }
  170. defer res.Body.Close()
  171. bodyBts, err := ioutil.ReadAll(res.Body)
  172. if err != nil {
  173. return
  174. }
  175. var data CustomerListResp
  176. err = json.Unmarshal(bodyBts, &data)
  177. if err != nil {
  178. return
  179. }
  180. if data.Errcode != 0 {
  181. return errors.New(fmt.Sprintf("errcode: %v,errmsg: %v", data.Errcode, data.Errmsg)), nil
  182. }
  183. list = data.CustomerList
  184. return
  185. }
  186. // GetMsgList 读取消息
  187. func (a *WxApi) GetMsgList(cursor, token, openKfid string) (err error, hasMore int, nextCursor string, list []Msg) {
  188. err = a.refreshAccessToken()
  189. if err != nil {
  190. return
  191. }
  192. url := GetMsgUrl
  193. url = strings.ReplaceAll(url, "ACCESS_TOKEN", a.accessToken)
  194. body := MsgParam{
  195. Cursor: cursor,
  196. Token: token,
  197. Limit: 1000,
  198. VoiceFormat: 0,
  199. OpenKfid: openKfid,
  200. }
  201. bts, _ := json.Marshal(body)
  202. res, err := http.Post(url, "application/json", bytes.NewReader(bts))
  203. if err != nil {
  204. return
  205. }
  206. defer res.Body.Close()
  207. bodyBts, err := ioutil.ReadAll(res.Body)
  208. if err != nil {
  209. return
  210. }
  211. var data MsgListResp
  212. err = json.Unmarshal(bodyBts, &data)
  213. if err != nil {
  214. return
  215. }
  216. if data.Errcode != 0 {
  217. err = errors.New(fmt.Sprintf("errcode: %v,errmsg: %v", data.Errcode, data.Errmsg))
  218. return
  219. }
  220. hasMore = data.HasMore
  221. nextCursor = data.NextCursor
  222. for _, msg := range data.MsgList {
  223. var m Msg
  224. m.Msgid, _ = msg["msgid"].(string)
  225. m.OpenKfid, _ = msg["open_kfid"].(string)
  226. m.ExternalUserid, _ = msg["external_userid"].(string)
  227. m.SendTime, _ = msg["send_time"].(float64)
  228. m.Origin, _ = msg["origin"].(float64)
  229. m.ServicerUserid, _ = msg["servicer_userid"].(string)
  230. m.Msgtype, _ = msg["msgtype"].(string)
  231. if m.Msgtype != "" {
  232. content, _ := msg[m.Msgtype]
  233. eventBts, _ := json.Marshal(content)
  234. m.DataInfo = string(eventBts)
  235. if m.Msgtype == "event" {
  236. var event = make(map[string]interface{})
  237. _ = json.Unmarshal(eventBts, &event)
  238. if _, b := event["event_type"].(string); b {
  239. m.OpenKfid, _ = event["open_kfid"].(string)
  240. m.ExternalUserid, _ = event["external_userid"].(string)
  241. }
  242. }
  243. }
  244. list = append(list, m)
  245. }
  246. return
  247. }