quanshi.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. package quanshi
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "hongze/hz_crm_api/services/alarm_msg"
  7. "hongze/hz_crm_api/utils"
  8. "io/ioutil"
  9. "net/http"
  10. "strconv"
  11. "strings"
  12. "time"
  13. )
  14. // QsResp 全时数据返回结构体
  15. type QsResp struct {
  16. Code int64 `json:"code"`
  17. Data interface{} `json:"data"`
  18. Msg string `json:"msg"`
  19. RequestID string `json:"requestId"`
  20. TimeStamp int64 `json:"timeStamp"`
  21. }
  22. // TokenResp 获取token的结构体
  23. type TokenResp struct {
  24. CreateDate string `json:"createDate"`
  25. CreateTime int64 `json:"createTime"`
  26. CustomerCode string `json:"customerCode"`
  27. Expire int64 `json:"expire"`
  28. ProductID interface{} `json:"productId"`
  29. Token string `json:"token"`
  30. UserID int64 `json:"userId"`
  31. UserName string `json:"userName"`
  32. }
  33. // getToken 获取token
  34. func getToken() (dataResp TokenResp, err error) {
  35. defer func() {
  36. if err != nil {
  37. go alarm_msg.SendAlarmMsg("获取全时token失败;ERR:"+err.Error(), 3)
  38. }
  39. }()
  40. user := new(QsUser)
  41. user.UserId = utils.QsUserId
  42. user.UserName = utils.QsUserName
  43. postData, err := json.Marshal(user)
  44. if err != nil {
  45. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  46. return
  47. }
  48. utils.FileLog.Info("Qs PostData:" + string(postData))
  49. postUrl := `https://events-openapi.quanshi.com/eventopenapi/token/create`
  50. respData, err, errMsg := postCurl(postUrl, string(postData), 1, false)
  51. if err != nil {
  52. fmt.Println("err:", err, ";errMsg:", errMsg)
  53. return
  54. }
  55. bodyBytes, _ := json.Marshal(respData.Data)
  56. err = json.Unmarshal(bodyBytes, &dataResp)
  57. return
  58. }
  59. // postCurl post请求上海接口
  60. func postCurl(urlStr string, postDataStr string, num int, isNeedToken bool) (respData QsResp, err error, errMsg string) {
  61. logMsg := ``
  62. utils.FileLog.Info("Qs PostData:" + postDataStr)
  63. client := &http.Client{}
  64. req, err := http.NewRequest("POST", urlStr, strings.NewReader(postDataStr))
  65. if err != nil {
  66. // handle error
  67. }
  68. nonce := utils.GetRandStringNoSpecialChar(32)
  69. curTime := time.Now().Local().UnixNano() / 1e6
  70. curTimeStr := strconv.FormatInt(curTime, 10)
  71. checkSumStr := utils.QsSecretKey + nonce + curTimeStr
  72. checkSum := utils.Sha1(checkSumStr)
  73. if isNeedToken {
  74. token, tmpErr := GetQsToken(false)
  75. if tmpErr != nil {
  76. err = tmpErr
  77. }
  78. req.Header.Set("token", token)
  79. }
  80. req.Header.Set("AppKey", utils.QsAppID)
  81. req.Header.Set("Content-Type", "application/json")
  82. req.Header.Set("accept", "application/json")
  83. req.Header.Set("Nonce", nonce)
  84. req.Header.Set("CurTime", curTimeStr)
  85. req.Header.Set("CheckSum", checkSum)
  86. resp, err := client.Do(req)
  87. if err != nil {
  88. logMsg = fmt.Sprint("post err; request:", postDataStr, "; errMsg:", err.Error())
  89. utils.FileLog.Info(logMsg)
  90. return
  91. }
  92. defer resp.Body.Close()
  93. body, err := ioutil.ReadAll(resp.Body)
  94. if err != nil {
  95. logMsg = fmt.Sprint("post err; request:", postDataStr, "; errMsg:", err.Error())
  96. utils.FileLog.Info(logMsg)
  97. return
  98. }
  99. utils.FileLog.Info(fmt.Sprint("Qs Post Result", ";url:", urlStr, ";\nparams:", postDataStr, ";\nresponse:", string(body)))
  100. err = json.Unmarshal(body, &respData)
  101. if err != nil {
  102. utils.FileLog.Info("post Err:", err.Error(), ";url:", urlStr, ";params:", postDataStr, ";response:", string(body))
  103. err = errors.New("Unmarshal Err:" + err.Error())
  104. return
  105. }
  106. //如果是token失效,同时只是第一次请求(没有尝试强制刷新token,那么重新请求)
  107. if respData.Code == 4100 && num <= 0 {
  108. //token失效
  109. _, tmpErr := refreshAccessToken()
  110. if tmpErr != nil {
  111. err = tmpErr
  112. }
  113. num++
  114. return postCurl(urlStr, postDataStr, num, isNeedToken)
  115. } else if respData.Code != 200 {
  116. utils.FileLog.Info(fmt.Sprint("post data err", ";url:", urlStr, ";params:", postDataStr, ";response:", string(body)))
  117. err = errors.New(respData.Msg)
  118. return
  119. }
  120. return
  121. }
  122. // refreshAccessToken 强制刷新获取accessToken
  123. func refreshAccessToken() (token string, err error) {
  124. defer func() {
  125. if err != nil {
  126. go alarm_msg.SendAlarmMsg("刷新上海的token失败;ERR:"+err.Error(), 3)
  127. //go utils.SendEmail(utils.APPNAME+"刷新上海的token失败:"+time.Now().Format("2006-01-02 15:04:05"), err.Error(), utils.EmailSendToUsers)
  128. }
  129. }()
  130. tokenResp, tmpErr := getToken()
  131. if tmpErr != nil {
  132. err = tmpErr
  133. return
  134. }
  135. token = tokenResp.Token
  136. //token存入redis
  137. err = utils.Rc.Put("QS_TOKEN", token, time.Duration(tokenResp.Expire-600)*time.Second)
  138. if err != nil {
  139. go alarm_msg.SendAlarmMsg("获取全时的token失败;全时token存入redis失败,ERR:"+err.Error(), 3)
  140. }
  141. return
  142. }
  143. type QsUser struct {
  144. UserId int64 `json:"userId"`
  145. UserName string `json:"userName"`
  146. }
  147. // GetQsToken 获取全时的token
  148. func GetQsToken(isRefresh bool) (token string, err error) {
  149. defer func() {
  150. if err != nil {
  151. go alarm_msg.SendAlarmMsg("获取上海的token失败,ERR:"+err.Error(), 3)
  152. //go utils.SendEmail(utils.APPNAME+"获取上海的token失败:"+time.Now().Format("2006-01-02 15:04:05"), err.Error(), utils.EmailSendToUsers)
  153. }
  154. }()
  155. token, redisErr := utils.Rc.RedisString("QS_TOKEN")
  156. //如果从redis中accessToken 获取失败或者token为空了,再或者需要强制刷新了,那么重新获取accessToken
  157. if redisErr != nil || token == `` || isRefresh {
  158. return refreshAccessToken()
  159. }
  160. return
  161. }
  162. // EventListParam 获取会议列表请求参数据结构
  163. type EventListParam struct {
  164. //Token string `json:"token"`
  165. //HostId int `description:"主持人ID 如果主持人ID为空,则查询所有创建的直播会议" json:"hostId"`
  166. StartTime int64 `description:"查询开始时间(时间戳,单位秒)默认为当前时间" json:"startTime"`
  167. EndTime int64 `description:"查询结束时间(时间戳,单位秒)默认为当前时间之后3个月" json:"endTime"`
  168. Limit int `description:"每页返回多少条记录,默认值10" json:"limit"`
  169. }
  170. // EventListResp 会议列表返回数据结构
  171. type EventListResp struct {
  172. AllowH323 int64 `json:"allowH323" description:""`
  173. AttendeeJoinURL string `json:"attendeeJoinUrl" description:"参会人入会链接"`
  174. AudienceUnionURL string `json:"audienceUnionUrl" description:"观众落地页链接"`
  175. BillingCode string `json:"billingCode" description:"云会议计费BC"`
  176. CallbackURL string `json:"callbackUrl" description:"会议回调地址"`
  177. ConfNodeType int64 `json:"confNodeType" description:"会议节点类型 0: 保密会议,1: 标准会议(默认)"`
  178. ConferenceID string `json:"conferenceId" description:"云会议ID"`
  179. CustomStr interface{} `json:"customStr" description:"自定义内容"`
  180. CustomerCode string `json:"customerCode" description:"客户编码"`
  181. EndDate string `json:"endDate" description:"会议结束时间(格式:年月日时分秒)"`
  182. EndTime int64 `json:"endTime" description:"会议结束时间(时间戳,单位秒)"`
  183. EventForm int64 `json:"eventForm" description:"会议形式 1: 电话活动,3: 网络会议,7: 大型直播活动"`
  184. EventID int64 `json:"eventId" description:"直播会议ID"`
  185. EventWatchword string `json:"eventWatchword" description:""`
  186. GuestJoinURL string `json:"guestJoinUrl" description:"嘉宾入会链接"`
  187. HostID int64 `json:"hostId" description:"主持人ID"`
  188. HostJoinURL string `json:"hostJoinUrl" description:"创建人入会链接"`
  189. HostName string `json:"hostName" description:"主持人姓名"`
  190. JoinHostURL string `json:"joinHostUrl" description:"助理主持人链接"`
  191. JointHostURL string `json:"jointHostUrl" description:""`
  192. Labels []string `json:"labels" description:"活动标签"`
  193. Length int64 `json:"length" description:"会议时长(时间戳,单位分钟)"`
  194. LiveCover string `json:"liveCover" description:"活动间(直播)封面图URL"`
  195. LiveLag int64 `json:"liveLag" description:"直播延迟设置(0:正常延迟,1:无延迟,默认0)"`
  196. LiveOpenFlag int64 `json:"liveOpenFlag" description:"开启实时互动直播 0: 否, 1: 是(默认值0,仅针对eventForm=3有效)"`
  197. LivePullURL string `json:"livePullUrl" description:"直播链接"`
  198. LiveScreen int64 `json:"liveScreen" description:"云活动手机屏幕显示方式,0:横屏(默认)1:竖屏"`
  199. ManualService int64 `json:"manualService" description:"是否需要项目经理开关,1:开启,2:关闭,默认2"`
  200. ModifyDate string `json:"modifyDate" description:""`
  201. ModifyTime int64 `json:"modifyTime" description:""`
  202. OpenWatchword int64 `json:"openWatchword" description:""`
  203. Pcode1 string `json:"pcode1" description:""`
  204. Pcode2 string `json:"pcode2" description:""`
  205. StartDate string `json:"startDate" description:"会议开始时间(格式:年月日时分秒)"`
  206. StartTime int64 `json:"startTime" description:"会议开始时间(时间戳,单位秒)"`
  207. Summary string `json:"summary" description:"会议概要"`
  208. Title string `json:"title" description:"会议主题"`
  209. WcallURL string `json:"wcallUrl" description:"云会议电话会议链接"`
  210. WebMeetURL string `json:"webMeetUrl" description:""`
  211. WebRTCUrl string `json:"webRTCUrl" description:"webRTC 入会链接"`
  212. }
  213. // GetQsEventList 获取会议列表
  214. func GetQsEventList(createTime, endTime time.Time) (dataResp []EventListResp, err error) {
  215. params := EventListParam{
  216. //HostId: 0,
  217. StartTime: createTime.Unix(),
  218. EndTime: endTime.Unix(),
  219. Limit: 10,
  220. }
  221. postData, err := json.Marshal(params)
  222. if err != nil {
  223. fmt.Println("PostData json.Marshal Err:" + err.Error())
  224. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  225. return
  226. }
  227. fmt.Println("postData:" + string(postData))
  228. utils.FileLog.Info("Qs PostData:" + string(postData))
  229. postUrl := `https://events-openapi.quanshi.com/eventopenapi/event/list`
  230. respData, err, errMsg := postCurl(postUrl, string(postData), 1, true)
  231. if err != nil {
  232. fmt.Println("err:", err, ";errMsg:", errMsg)
  233. return
  234. }
  235. bodyBytes, _ := json.Marshal(respData.Data)
  236. err = json.Unmarshal(bodyBytes, &dataResp)
  237. return
  238. }
  239. // EventCreateParams 全时会议创建请求参数据结构
  240. type EventCreateParams struct {
  241. HostId int64 `json:"hostId" description:"主持人ID"`
  242. Title string `json:"title" description:"会议主题, 主题不能超过30个字"`
  243. StartTime int64 `json:"startTime" description:"开始时间(时间戳,单位秒)"`
  244. Length int `json:"length" description:"会议时长(单位分钟)会议时长的取值只接受30的倍数,并且最大为720分钟. 如果填写的时长不符合要求,系统自动取最接近的分钟数. 例如输入时长40分钟,则系统自动转换成30分钟;而输入时长50分钟,系统会调整为60分钟"`
  245. EventForm int `json:"eventForm" description:"会议形式 1: 电话会议,3: 网络会议,7: 大型直播活动;电话会议 :通过电话的方式召开的活动,可进行声音的实时互动,无资料共享。;网络会议:适用于有资料共享的实时互动活动,所有参会用户都可查看共享的资料,可选择电话/网络语音进行互动讨论。;大型直播活动:适用于宣讲路演、带货推广、年会、在线发布会,所有参会用户可通过网页/小程序观看直播,可通过文字或举手方式进行互动讨论。"`
  246. CallbackUrl string `json:"callbackUrl" description:"会议回调地址"`
  247. JoinLimit int `json:"joinLimit" description:"观众直播入会限制 0: 公开, 1: 白名单(默认, 并且非白名单(电话入会)拒绝入会)"`
  248. ManualService int `json:"manualService" description:"是否需要项目经理开关,1: 开启,2: 关闭(默认1)"`
  249. }
  250. // EventCreateResp 全时会议创建 返回 参数据结构
  251. type EventCreateResp struct {
  252. AttendeeJoinURL string `json:"attendeeJoinUrl" description:"参会人入会链接"`
  253. AudienceUnionURL string `json:"audienceUnionUrl" description:"观众落地页链接"`
  254. BillingCode string `json:"billingCode" description:"云会议计费BC"`
  255. CallbackURL string `json:"callbackUrl" description:"会议回调地址"`
  256. ConfNodeType int64 `json:"confNodeType" description:"会议节点类型 0: 保密会议,1: 标准会议(默认)"`
  257. ConferenceID string `json:"conferenceId" description:"云会议ID"`
  258. CustomStr string `json:"customStr" description:"自定义内容"`
  259. EventForm int64 `json:"eventForm" description:"会议形式 1: 电话活动,3: 网络会议,7: 大型直播活动"`
  260. EventID int64 `json:"eventId" description:"直播会议ID"`
  261. GuestJoinURL string `json:"guestJoinUrl" description:"嘉宾入会链接"`
  262. HostID int64 `json:"hostId" description:"主持人ID"`
  263. HostJoinURL string `json:"hostJoinUrl" description:"主持人入会链接"`
  264. JoinHostURL string `json:"joinHostUrl" description:"助理主持人链接"`
  265. JoinLimit int64 `json:"joinLimit" description:"观众直播入会限制 0: 公开, 1: 白名单(默认值1, 并且非白名单(电话入会)拒绝入会)"`
  266. Labels []string `json:"labels" description:"活动标签"`
  267. Length int64 `json:"length" description:"会议时长(单位分钟);会议时长的取值只接受30的倍数,并且最大为720分钟. 如果填写的时长不符合要求,系统自动取最接近的分钟数. 例如输入时长40分钟,则系统自动转换成30分钟;而输入时长50分钟,系统会调整为60分钟"`
  268. LiveCover string `json:"liveCover" description:"会议封面图URL 尺寸1280x720px 图片小于2MB(jpg、png)"`
  269. LiveLag int64 `json:"liveLag" description:"直播延迟设置 0: 正常延迟,1: 无延迟(默认0)"`
  270. LiveOpenFlag int64 `json:"liveOpenFlag" description:"开启实时互动直播 0: 否, 1: 是(默认值0,仅针对eventForm=3有效)"`
  271. LiveScreen int64 `json:"liveScreen" description:"云活动手机屏幕显示方式,0: 横屏,1: 竖屏(默认0)"`
  272. ManualService int64 `json:"manualService" description:"是否需要项目经理开关,1: 开启,2: 关闭(默认2)"`
  273. Pcode1 string `json:"pcode1" description:"主持人入会密码"`
  274. Pcode2 string `json:"pcode2" description:"参会人入会密码"`
  275. StartTime int64 `json:"startTime" description:"会议开始时间(时间戳,单位秒)"`
  276. Summary string `json:"summary" description:"会议概要"`
  277. Title string `json:"title" description:"会议主题"`
  278. Wcallurl string `json:"wcallurl" description:"云会议电话会议链接"`
  279. }
  280. // QsEventCreate 全时会议创建
  281. func QsEventCreate(title string, meetingTime, eventForm int, startTime time.Time, callbackUrl string) (dataResp EventCreateResp, err error) {
  282. defer func() {
  283. if err != nil {
  284. go alarm_msg.SendAlarmMsg("创建全时会议失败;ERR:"+err.Error(), 3)
  285. }
  286. }()
  287. isManualService := 2 //是否需要项目经理提醒(默认不需要)
  288. joinLimit := 0
  289. params := EventCreateParams{
  290. HostId: utils.QsUserId,
  291. Title: title,
  292. StartTime: startTime.Unix(),
  293. Length: meetingTime,
  294. EventForm: eventForm,
  295. CallbackUrl: callbackUrl,
  296. JoinLimit: joinLimit,
  297. ManualService: isManualService,
  298. }
  299. postData, err := json.Marshal(params)
  300. if err != nil {
  301. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  302. return
  303. }
  304. postUrl := `https://events-openapi.quanshi.com/eventopenapi/event/create`
  305. respData, err, errMsg := postCurl(postUrl, string(postData), 1, true)
  306. if err != nil {
  307. fmt.Println("err:", err, ";errMsg:", errMsg)
  308. return
  309. }
  310. bodyBytes, _ := json.Marshal(respData.Data)
  311. err = json.Unmarshal(bodyBytes, &dataResp)
  312. return
  313. }
  314. // EventCancelParams 全时会议取消请求参数据结构
  315. type EventCancelParams struct {
  316. EventId int64 `json:"eventId" description:"全时会议id"`
  317. }
  318. // QsEventCancel 取消全时会议
  319. func QsEventCancel(eventId int) (err error) {
  320. defer func() {
  321. if err != nil {
  322. go alarm_msg.SendAlarmMsg("取消全时会议失败;ERR:"+err.Error(), 3)
  323. }
  324. }()
  325. params := EventCancelParams{
  326. EventId: int64(eventId),
  327. }
  328. postData, err := json.Marshal(params)
  329. if err != nil {
  330. fmt.Println("PostData json.Marshal Err:" + err.Error())
  331. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  332. return
  333. }
  334. postUrl := `https://events-openapi.quanshi.com/eventopenapi/event/cancel`
  335. _, err, errMsg := postCurl(postUrl, string(postData), 1, true)
  336. if err != nil {
  337. fmt.Println("err:", err, ";errMsg:", errMsg)
  338. return
  339. }
  340. return
  341. }
  342. // EventUpdateParams 全时会议修改请求参数据结构
  343. type EventUpdateParams struct {
  344. Title string `json:"title"`
  345. StartTime int64 `json:"startTime"`
  346. Length int `json:"length"`
  347. EventId int64 `json:"eventId"`
  348. UseWaitingRoom int64 `json:"useWaitingRoom"`
  349. }
  350. // EventUpdateResp 全时会议修改 返回 数据结构
  351. type EventUpdateResp struct {
  352. AttendeeJoinURL string `json:"attendeeJoinUrl"`
  353. AudienceUnionURL string `json:"audienceUnionUrl"`
  354. BillingCode string `json:"billingCode"`
  355. CallbackURL string `json:"callbackUrl"`
  356. ConfNodeType int64 `json:"confNodeType"`
  357. ConferenceID string `json:"conferenceId"`
  358. CustomStr string `json:"customStr"`
  359. EventForm int64 `json:"eventForm"`
  360. EventID int64 `json:"eventId"`
  361. GuestJoinURL string `json:"guestJoinUrl"`
  362. HostID int64 `json:"hostId"`
  363. HostJoinURL string `json:"hostJoinUrl"`
  364. JoinHostURL string `json:"joinHostUrl"`
  365. JoinLimit int64 `json:"joinLimit"`
  366. Labels []string `json:"labels"`
  367. Length int64 `json:"length"`
  368. LiveCover string `json:"liveCover"`
  369. LiveLag int64 `json:"liveLag"`
  370. LiveOpenFlag int64 `json:"liveOpenFlag"`
  371. LiveScreen int64 `json:"liveScreen"`
  372. ManualService int64 `json:"manualService"`
  373. Pcode1 string `json:"pcode1"`
  374. Pcode2 string `json:"pcode2"`
  375. StartTime int64 `json:"startTime"`
  376. Summary string `json:"summary"`
  377. Title string `json:"title"`
  378. Wcallurl string `json:"wcallurl"`
  379. }
  380. // QsEventUpdate 全时会议修改
  381. func QsEventUpdate(eventId, length int, title string, startTime time.Time) (dataResp EventUpdateResp, err error) {
  382. params := EventUpdateParams{
  383. EventId: int64(eventId),
  384. Title: title,
  385. StartTime: startTime.Unix(),
  386. Length: length,
  387. }
  388. postData, err := json.Marshal(params)
  389. if err != nil {
  390. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  391. return
  392. }
  393. postUrl := `https://events-openapi.quanshi.com/eventopenapi/event/update`
  394. respData, err, errMsg := postCurl(postUrl, string(postData), 1, true)
  395. if err != nil {
  396. fmt.Println("err:", err, ";errMsg:", errMsg)
  397. return
  398. }
  399. bodyBytes, _ := json.Marshal(respData.Data)
  400. err = json.Unmarshal(bodyBytes, &dataResp)
  401. return
  402. }
  403. // UserEmailParams 全时 根据邮箱获取用户信息 请求参数据结构
  404. type UserEmailParams struct {
  405. Email string `json:"email"`
  406. }
  407. // UserInfoResp 全时用户信息 返回 数据结构
  408. type UserInfoResp struct {
  409. AccountType int64 `json:"accountType" description:"账号类型 0: 个人账号(个人站点或电商站点下的账号); 1: 企业账号(非个人站点、电商站点的账号)"`
  410. CountryCode string `json:"countryCode" description:"国家码"`
  411. CustomerCode string `json:"customerCode" description:"客户编码"`
  412. CustomerName string `json:"customerName" description:"客户名称"`
  413. DisplayName string `json:"displayName" description:"显示名称"`
  414. Email string `json:"email" description:"邮箱"`
  415. FirstName string `json:"firstName" description:"首部名称"`
  416. LastName string `json:"lastName" description:"尾部名称"`
  417. LoginName string `json:"loginName" description:"登录名"`
  418. MiddleName string `json:"middleName" description:"中间名称"`
  419. Mobile string `json:"mobile" description:"手机"`
  420. ProductStatus int64 `json:"productStatus" description:"产品类型 0: 未知状态 1: 已开通 2: 未开通 默认为0"`
  421. Products []struct {
  422. AccountCostStatus int64 `json:"accountCostStatus" description:"费用状态 82-正式,9-试用,91-过期,81-欠费,71-合同终止;过期或者欠费的不能启用产品,需要先由qsboss系统修改为正式或者试用账号,61-免费账号,62-付费账号"`
  423. AccountStatus int64 `json:"accountStatus" description:"账号状态 9:试用 82:正式 91:过期 81:欠费 0:禁用"`
  424. ProductID int64 `json:"productId" description:" 产品ID"`
  425. } `json:"products" description:"产品列表"`
  426. UserID int64 `json:"userId" description:"用户ID"`
  427. UserStatus int64 `json:"userStatus" description:"用户状态 0:未激活; 1:已激活; 2:已关闭"`
  428. }
  429. // GetQsUserInfoByEmail 根据邮箱号获取全时用户信息
  430. func GetQsUserInfoByEmail(email string) (dataResp UserInfoResp, err error) {
  431. userEmailItem := UserEmailParams{
  432. Email: email,
  433. }
  434. postData, err := json.Marshal(userEmailItem)
  435. if err != nil {
  436. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  437. return
  438. }
  439. postUrl := `https://events-openapi.quanshi.com/eventopenapi/user/search/email`
  440. respData, err, errMsg := postCurl(postUrl, string(postData), 1, true)
  441. if err != nil {
  442. fmt.Println("err:", err, ";errMsg:", errMsg)
  443. return
  444. }
  445. bodyBytes, _ := json.Marshal(respData.Data)
  446. err = json.Unmarshal(bodyBytes, &dataResp)
  447. return
  448. }
  449. type UserInfo struct {
  450. Mobiles []*UserMobile `json:"mobiles"`
  451. }
  452. type UserMobile struct {
  453. PhoneNumber string `json:"phoneNumber"`
  454. }
  455. func GetQsUserInfoByPhone() {
  456. userMobileItem := new(UserMobile)
  457. userMobileItem.PhoneNumber = "17521741003"
  458. userInfoItem := new(UserInfo)
  459. userInfoItem.Mobiles = append(userInfoItem.Mobiles, userMobileItem)
  460. postData, err := json.Marshal(userInfoItem)
  461. if err != nil {
  462. fmt.Println("PostData json.Marshal Err:" + err.Error())
  463. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  464. return
  465. }
  466. fmt.Println("postData:" + string(postData))
  467. utils.FileLog.Info("Qs PostData:" + string(postData))
  468. client := &http.Client{}
  469. postUrl := `https://events-openapi.quanshi.com//eventopenapi/user/search/mobiles`
  470. req, err := http.NewRequest("POST", postUrl, strings.NewReader(string(postData)))
  471. if err != nil {
  472. // handle error
  473. }
  474. nonce := utils.GetRandStringNoSpecialChar(32)
  475. curTime := time.Now().Local().UnixNano() / 1e6
  476. curTimeStr := strconv.FormatInt(curTime, 10)
  477. checkSumStr := utils.QsSecretKey + nonce + curTimeStr
  478. checkSum := utils.Sha1(checkSumStr)
  479. req.Header.Set("AppKey", utils.QsAppID)
  480. req.Header.Set("Content-Type", "application/json")
  481. req.Header.Set("accept", "application/json")
  482. req.Header.Set("Nonce", nonce)
  483. req.Header.Set("CurTime", curTimeStr)
  484. req.Header.Set("CheckSum", checkSum)
  485. resp, err := client.Do(req)
  486. defer resp.Body.Close()
  487. body, err := ioutil.ReadAll(resp.Body)
  488. if err != nil {
  489. // handle error
  490. }
  491. utils.FileLog.Info("Qs Result:" + string(body))
  492. fmt.Println(string(body))
  493. }
  494. // EventStatusParams 查看会议状态请求结构体
  495. type EventStatusParams struct {
  496. EventId int64 `json:"eventId"`
  497. }
  498. // EventStatusResp 查看会议状态结果返回结构体
  499. type EventStatusResp struct {
  500. AdvanceHours string `json:"advanceHours"`
  501. Attendees int64 `json:"attendees"`
  502. EventID int64 `json:"eventId"`
  503. EventStatus int64 `json:"eventStatus"`
  504. MayJoin int64 `json:"mayJoin"`
  505. }
  506. // QsEventStatus 查看会议状态
  507. func QsEventStatus(eventId int64) (dataResp EventStatusResp, err error) {
  508. params := EventStatusParams{EventId: eventId}
  509. postData, err := json.Marshal(params)
  510. if err != nil {
  511. fmt.Println("PostData json.Marshal Err:" + err.Error())
  512. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  513. return
  514. }
  515. postUrl := `https://events-openapi.quanshi.com/eventopenapi/event/status`
  516. respData, err, errMsg := postCurl(postUrl, string(postData), 1, true)
  517. if err != nil {
  518. fmt.Println("err:", err, ";errMsg:", errMsg)
  519. return
  520. }
  521. bodyBytes, _ := json.Marshal(respData.Data)
  522. err = json.Unmarshal(bodyBytes, &dataResp)
  523. return
  524. }
  525. // EventDetailParams 查看会议详情请求结构体
  526. type EventDetailParams struct {
  527. EventId int64 `json:"eventId"`
  528. }
  529. // EventDetailResp 查看会议详情结果返回结构体
  530. type EventDetailResp struct {
  531. AdvanceHours string `json:"advanceHours"`
  532. Attendees int64 `json:"attendees"`
  533. EventID int64 `json:"eventId"`
  534. EventStatus int64 `json:"eventStatus"`
  535. MayJoin int64 `json:"mayJoin"`
  536. }
  537. // QsEventDetail 查看会议详情
  538. func QsEventDetail(eventId int64) (dataResp EventUpdateResp, err error) {
  539. params := EventDetailParams{EventId: eventId}
  540. postData, err := json.Marshal(params)
  541. if err != nil {
  542. fmt.Println("PostData json.Marshal Err:" + err.Error())
  543. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  544. return
  545. }
  546. postUrl := `https://events-openapi.quanshi.com/eventopenapi/event/info`
  547. respData, err, errMsg := postCurl(postUrl, string(postData), 1, true)
  548. if err != nil {
  549. fmt.Println("err:", err, ";errMsg:", errMsg)
  550. return
  551. }
  552. bodyBytes, _ := json.Marshal(respData.Data)
  553. err = json.Unmarshal(bodyBytes, &dataResp)
  554. return
  555. }
  556. // QsEventReportSummaryParams 查看会议汇总数据请求结构体
  557. type QsEventReportSummaryParams struct {
  558. EventId int64 `json:"eventId" description:"直播会议ID"`
  559. SortBy string `json:"sortBy" description:"汇总去重条件 默认值 extId; email: 根据邮箱汇总; mobile: 根据手机汇总; name: 根据姓名汇总; extId: 根据第三方ID汇总"`
  560. }
  561. // QsEventReportSummaryResp 查看会议汇总数据结果返回结构体
  562. type QsEventReportSummaryResp struct {
  563. EventID int64 `json:"eventId"`
  564. SortBy string `json:"sortBy"`
  565. Summary map[string]struct {
  566. BillingCode string `json:"billingCode"`
  567. ConferenceID string `json:"conferenceId"`
  568. Duration int64 `json:"duration"`
  569. Email string `json:"email"`
  570. ExtID string `json:"extId"`
  571. HostID string `json:"hostId"`
  572. Mobile string `json:"mobile"`
  573. Name string `json:"name"`
  574. OfflineDate string `json:"offline_date"`
  575. OfflineTime int64 `json:"offline_time"`
  576. OnlineDate string `json:"online_date"`
  577. OnlineTime int64 `json:"online_time"`
  578. } `json:"summary"`
  579. }
  580. // QsEventReportSummary 查看会议汇总数据
  581. func QsEventReportSummary(eventId int) (dataResp QsEventReportSummaryResp, err error) {
  582. sortBy := `mobile`
  583. params := QsEventReportSummaryParams{
  584. EventId: int64(eventId),
  585. SortBy: sortBy,
  586. }
  587. postData, err := json.Marshal(params)
  588. if err != nil {
  589. fmt.Println("PostData json.Marshal Err:" + err.Error())
  590. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  591. return
  592. }
  593. postUrl := `https://events-openapi.quanshi.com/eventopenapi/event/report/summary`
  594. respData, err, errMsg := postCurl(postUrl, string(postData), 1, true)
  595. if err != nil {
  596. fmt.Println("err:", err, ";errMsg:", errMsg)
  597. return
  598. }
  599. bodyBytes, _ := json.Marshal(respData.Data)
  600. err = json.Unmarshal(bodyBytes, &dataResp)
  601. return
  602. }
  603. // QsEventReportQueryParams 批量查询会议状态和录制数据请求结构体
  604. type QsEventReportQueryParams struct {
  605. EventIds []int64 `json:"eventIds" description:"直播会议ID"`
  606. QueryType int64 `json:"queryType" description:"查询的数据类别(1: 会议状态; 2: 会议录制; 3: 会议状态+会议录制)"`
  607. RecordType int `json:"recordType" description:"录制类型(queryType=2时有效)1:会议录制或电话录制; 5:直播录制; 默认全查"`
  608. }
  609. // QsEventReportQueryResp 批量查询会议状态和录制数据结果返回结构体
  610. type QsEventReportQueryResp struct {
  611. Records map[string]struct {
  612. RecordID int64 `json:"recordId"`
  613. RecordType int64 `json:"recordType"`
  614. RecordingEndDate string `json:"recordingEndDate"`
  615. RecordingEndtime int64 `json:"recordingEndtime"`
  616. RecordingStartDate string `json:"recordingStartDate"`
  617. RecordingStarttime int64 `json:"recordingStarttime"`
  618. Thumb string `json:"thumb"`
  619. Title string `json:"title"`
  620. VideoLength int64 `json:"videoLength"`
  621. VideoSize int64 `json:"videoSize"`
  622. VideoStreamURL string `json:"videoStreamUrl"`
  623. VideoURL string `json:"videoURL"`
  624. } `json:"records"`
  625. Status map[string]struct {
  626. ConferenceID string `json:"conferenceId"`
  627. Status int64 `json:"status"`
  628. TempConferenceID string `json:"tempConferenceId"`
  629. UserID int64 `json:"userId"`
  630. } `json:"status"`
  631. }
  632. // QsEventReportQueryVideo 批量查询会议录制数据
  633. func QsEventReportQueryVideo(eventId int64) (dataResp QsEventReportQueryResp, err error) {
  634. params := QsEventReportQueryParams{
  635. EventIds: []int64{eventId},
  636. QueryType: 2,
  637. RecordType: 1,
  638. }
  639. postData, err := json.Marshal(params)
  640. if err != nil {
  641. fmt.Println("PostData json.Marshal Err:" + err.Error())
  642. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  643. return
  644. }
  645. postUrl := `https://events-openapi.quanshi.com/eventopenapi/event/report/query`
  646. respData, err, errMsg := postCurl(postUrl, string(postData), 1, true)
  647. if err != nil {
  648. fmt.Println("err:", err, ";errMsg:", errMsg)
  649. return
  650. }
  651. bodyBytes, _ := json.Marshal(respData.Data)
  652. err = json.Unmarshal(bodyBytes, &dataResp)
  653. return
  654. }
  655. // QsEventReportQuery 批量查询会议状态和录制数据
  656. func QsEventReportQuery(eventId, queryType int64) (dataResp QsEventReportQueryResp, err error) {
  657. //recordType := 0
  658. params := QsEventReportQueryParams{
  659. EventIds: []int64{eventId},
  660. QueryType: queryType,
  661. //RecordType: recordType,
  662. }
  663. postData, err := json.Marshal(params)
  664. if err != nil {
  665. fmt.Println("PostData json.Marshal Err:" + err.Error())
  666. utils.FileLog.Info("PostData json.Marshal Err:" + err.Error())
  667. return
  668. }
  669. postUrl := `https://events-openapi.quanshi.com/eventopenapi/event/report/query`
  670. respData, err, errMsg := postCurl(postUrl, string(postData), 1, true)
  671. if err != nil {
  672. fmt.Println("err:", err, ";errMsg:", errMsg)
  673. return
  674. }
  675. bodyBytes, _ := json.Marshal(respData.Data)
  676. err = json.Unmarshal(bodyBytes, &dataResp)
  677. return
  678. }
  679. // 弘则全时的回调签名秘钥
  680. const QS_HONGZE_KEY = "hongZe20220601QSROc"
  681. // GetSign 获取签名
  682. func GetSign(signStr string) string {
  683. signStr += "&key=" + QS_HONGZE_KEY
  684. return utils.MD5(signStr)
  685. }
  686. //func Qsinit() {
  687. // fmt.Println("start")
  688. // nonce := utils.GetRandStringNoSpecialChar(32)
  689. // curTime := time.Now().Local().UnixNano()/1e6
  690. // curTimeStr := strconv.FormatInt(curTime, 10)
  691. // checkSumStr := QsSecretKey + nonce + curTimeStr
  692. // fmt.Println("nonce:" + nonce)
  693. // fmt.Println("curTimeStr:" + curTimeStr)
  694. // fmt.Println("QsSecretKey:" + QsSecretKey)
  695. // checkSum := utils.Sha1(checkSumStr)
  696. // fmt.Println(checkSum)
  697. // fmt.Println("end")
  698. //}