push.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. package zoho
  2. import (
  3. "crm-api/pkg/configs"
  4. "crm-api/pkg/httpclient"
  5. "crm-api/pkg/lfshook"
  6. "encoding/json"
  7. "fmt"
  8. "io/ioutil"
  9. "net/http"
  10. "strconv"
  11. "time"
  12. "gopkg.in/ini.v1"
  13. )
  14. var TimestampList = make(map[string]string)
  15. var StartTimeList = make(map[string]time.Time) // 事件中 Timestamp 转 StartTime 有问题,重新记录时间
  16. // var CallTypeList = make(map[string]string) // 临时记录 incoming 和 outgoing
  17. var DialStatusList = make(map[string]string) // 临时记录 DialStatus:ANSWER NOANSWER
  18. // func addOneToStringNumber(s string) string {
  19. // num, err := strconv.Atoi(s)
  20. // if err != nil {
  21. // fmt.Println("xxxxxxxxxxxxx = ", err)
  22. // }
  23. // num++
  24. // return strconv.Itoa(num)
  25. // }
  26. func CallNotify(event map[string]string) {
  27. fmt.Println("=========================================== ")
  28. fmt.Println("event[] = ", event)
  29. fmt.Println("event = ", event["Event"])
  30. fmt.Println("AMIPushUrl = ", configs.PushConfigValue.AMIPushUrl)
  31. fmt.Println("Channel = ", event["Channel"])
  32. /* ===================不这样取callDest,删除 ====================
  33. var callDest string
  34. if event["Channel"] != "" {
  35. callDest = strings.Split(strings.Split(event["Channel"], "/")[1], "-")[0]
  36. fmt.Println("callDest = ", callDest)
  37. }
  38. // * ========================================================= */
  39. // var callId string
  40. // timestamp := time.Now().Unix()
  41. // rand.Seed(time.Now().UnixNano())
  42. // // 字符串
  43. // charset := "abcdefghijklmnopqrstuvwxyz"
  44. // // 获取随机字符
  45. // c := charset[rand.Intn(len(charset))]
  46. // callId = "callid" + strconv.Itoa(int(timestamp))
  47. // if callId == " " {
  48. // input := "callid100000"
  49. // num, err := strconv.Atoi(input)
  50. // if err != nil {
  51. // fmt.Println("x11111111111 = ", err)
  52. // }
  53. // num++
  54. // callId = strconv.Itoa(num)
  55. // fmt.Println("callId111111111 = ", callId)
  56. // } else {
  57. // num, err := strconv.Atoi(callId)
  58. // if err != nil {
  59. // fmt.Println("x22222222222222 = ", err)
  60. // }
  61. // num++
  62. // callId = strconv.Itoa(num)
  63. // fmt.Println("callId2222222222 = ", callId)
  64. // }
  65. var callId = "callid100007" // 测试用,每次测试 +1
  66. // event["Exten"] = "123456789" // 测试用
  67. // fmt.Println("callId = ", callId)
  68. var zohoUser = "872297346" // 测试用 872297346 873447071 // 后面看是否从数据库中取 t_zoho_user
  69. // var info TabZohouser
  70. // if _, err := mysql.DBOrmInstance.Insert(&info); err != nil {
  71. // lfshook.NewLogger().Error(err)
  72. // return
  73. // }
  74. // var zohoUser = info.UserId
  75. // 读取vtiger配置文件
  76. confPath := "/etc/asterisk/crm_api.conf"
  77. cfg, err := ini.Load(confPath)
  78. if err != nil {
  79. lfshook.NewLogger().Error(err)
  80. return
  81. }
  82. ZOHO_URL := cfg.Section("general").Key("zohoUrl").String()
  83. if ZOHO_URL == "" {
  84. lfshook.NewLogger().Error("/etc/asterisk/crm_api.conf not set zohoUrl")
  85. return
  86. }
  87. // var getURL string
  88. fmt.Println("Context = ", event["Context"])
  89. // 呼叫发起事件
  90. // if event["Event"] == "DialBegin" && event["Context"] == "macro-stdexten" {
  91. // if event["Event"] == "DialBegin" && strings.Compare(event["Context"], "macro-stdexten") == 0 {
  92. if event["Event"] == "DialBegin" {
  93. /* ===================先放这里测试用 ============================================================
  94. // 记录开始时间
  95. TimestampList[event["Uniqueid"]] = event["Timestamp"]
  96. // StartTimeList[event["Uniqueid"]] = time.Now().Format("2006-01-02 15:04:09")
  97. StartTimeList[event["Uniqueid"]] = time.Now()
  98. /* ===================先放这里测试用 ============================================================
  99. fmt.Printf("Uniqueid=%s\n", event["Uniqueid"])
  100. fmt.Printf("Timestamp=%s\n", event["Timestamp"])
  101. TimestampTmp, err := strconv.Atoi(event["Timestamp"]) // 不要
  102. if err != nil {
  103. fmt.Printf("转换出错: %v\n", err)
  104. return
  105. }
  106. fmt.Printf("TimestampAtoi=%d\n", TimestampTmp)
  107. TimestampTmp002, err := strconv.ParseFloat(event["Timestamp"], 64) // OK
  108. if err != nil {
  109. fmt.Printf("转换出错: %v\n", err)
  110. return
  111. }
  112. fmt.Printf("TimestampParseFloat=%f\n", TimestampTmp002)
  113. // * ===================================================================================== */
  114. // Outgoing Call - Ringing
  115. if event["Context"] == "macro-trunkdial-failover" {
  116. StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour)
  117. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=ringing&id=10031&from=123456789&to=12300000001
  118. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=ringing&id=%s&from=%s&to=%s", ZOHO_URL, callId, event["CallerIDNum"], event["DestCallerIDNum"])
  119. if zohoUser != "" {
  120. getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  121. }
  122. fmt.Println("getURL = ", getURL)
  123. go httpclient.ZohoGet(getURL)
  124. // Incoming Call - Ringing
  125. // if event["Context"] == "macro-stdexten" {
  126. } else if event["Context"] == "macro-stdexten" || event["Context"] == "macro-stdexten-withoutvm" { // 开启语音留言:macro-stdexten 关闭语音留言:macro-stdexten-withoutvm
  127. StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour)
  128. // if strings.Compare(event["Context"], "macro-stdexten") == 0 { // OK
  129. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=received&state=ringing&id=10033&from=12300000001&to=123456789
  130. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ringing&id=%s&from=%s&to=%s", ZOHO_URL, callId, event["Exten"], callDest) // 取得from to 可能不准
  131. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ringing&id=%s&from=%s&to=%s", ZOHO_URL, callId, event["CallerIDNum"], event["DestCallerIDNum"])
  132. if zohoUser != "" {
  133. getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  134. }
  135. fmt.Println("getURL = ", getURL)
  136. go httpclient.ZohoGet(getURL)
  137. }
  138. // 呼叫结束事件
  139. } else if event["Event"] == "DialEnd" {
  140. // 记录呼叫状态
  141. DialStatusList[event["Linkedid"]] = event["DialStatus"]
  142. // Outgoing Call - Unattended
  143. if event["Context"] == "macro-trunkdial-failover" && event["DialStatus"] != "ANSWER" {
  144. startTime := StartTimeList[event["Linkedid"]].Format("2006-01-02 15:04:09")
  145. fmt.Println("startTime: ", startTime)
  146. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=busy&id=10025&from=123456789&to=12300000001&start_time=2024-12-04 15:09:10
  147. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=busy&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, callId, event["CallerIDNum"], event["DestCallerIDNum"], startTime)
  148. if zohoUser != "" {
  149. getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  150. }
  151. fmt.Println("getURL = ", getURL)
  152. go httpclient.ZohoGet(getURL)
  153. // Incoming Call - Missed
  154. // if event["Context"] == "macro-stdexten" && event["DialStatus"] != "ANSWER" {
  155. } else if (event["Context"] == "macro-stdexten" || event["Context"] == "macro-stdexten-withoutvm") && event["DialStatus"] != "ANSWER" { // 开启语音留言:macro-stdexten 关闭语音留言:macro-stdexten-withoutvm
  156. startTime := StartTimeList[event["Linkedid"]].Format("2006-01-02 15:04:09")
  157. fmt.Println("startTime: ", startTime)
  158. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=received&state=missed&id=10005&from=12300000001&to=123456789&start_time=2024-12-04 15:09:10
  159. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=missed&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, callId, event["CallerIDNum"], event["DestCallerIDNum"], startTime)
  160. if zohoUser != "" {
  161. getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  162. }
  163. fmt.Println("getURL = ", getURL)
  164. go httpclient.ZohoGet(getURL)
  165. }
  166. // 呼叫已连接事件
  167. } else if event["Event"] == "BridgeEnter" {
  168. // Outgoing Call - Answered
  169. if event["Context"] == "macro-trunkdial-failover" && event["Priority"] == "1" { // 注意这里选择 Priority:1 的,便于确认 CallerIDNum,ConnectedLineNum
  170. // 记录开始时间
  171. // TimestampList[event["Uniqueid"]] = event["Timestamp"] // error 需要把 Uniqueid 改为 Linkedid
  172. // StartTimeList[event["Uniqueid"]] = time.Now() // error 需要把 Uniqueid 改为 Linkedid
  173. TimestampList[event["Linkedid"]] = event["Timestamp"]
  174. StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour)
  175. // https: //www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=answered&id=10003&from=123456789&to=12300000001
  176. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, callId, event["CallerIDNum"], event["ConnectedLineNum"])
  177. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDNum"])
  178. if zohoUser != "" {
  179. getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  180. }
  181. fmt.Println("getURL = ", getURL)
  182. go httpclient.ZohoGet(getURL)
  183. // Incoming Call - Answered
  184. // if event["Context"] == "macro-stdexten" {
  185. } else if event["Context"] == "macro-stdexten" || event["Context"] == "macro-stdexten-withoutvm" { // 开启语音留言:macro-stdexten 关闭语音留言:macro-stdexten-withoutvm
  186. // 记录开始时间
  187. // TimestampList[event["Uniqueid"]] = event["Timestamp"] // Uniqueid 有时通话也不合适 NG // 都改为 Linkedid
  188. // StartTimeList[event["Uniqueid"]] = time.Now() // Uniqueid 有时通话也不合适 NG // 都改为 Linkedid
  189. TimestampList[event["Linkedid"]] = event["Timestamp"] // 呼入时设置 Uniqueid 不是 Linkedid
  190. StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour) // 呼入时设置 Uniqueid 不是 Linkedid
  191. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=received&state=answered&id=10023&from=12300000001&to=123456789
  192. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, callId, event["CallerIDNum"], event["ConnectedLineNum"])
  193. if zohoUser != "" {
  194. getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  195. }
  196. fmt.Println("getURL = ", getURL)
  197. go httpclient.ZohoGet(getURL)
  198. }
  199. // 呼叫挂断事件
  200. } else if event["Event"] == "HangupRequest" {
  201. /* ===================先放这里测试用 ============================================================
  202. // 记录结束时间
  203. // TimestampList[event["Uniqueid"]] = event["Timestamp"]
  204. // startTimeStamp := int64(TimestampList[event["Uniqueid"]])
  205. fmt.Println("startTimeStamp Str: ", TimestampList[event["Uniqueid"]])
  206. // keyTmp := event["Uniqueid"]
  207. // fmt.Println("keyTmp: ", keyTmp)
  208. // fmt.Println("startTimeStamp Str: ", TimestampList[keyTmp])
  209. startTimeStamp, err := strconv.ParseFloat(TimestampList[event["Uniqueid"]], 64) // OK
  210. if err != nil {
  211. fmt.Printf("startTimeStamp转换出错: %v\n", err)
  212. return
  213. }
  214. fmt.Printf("startTimeStamp=%f\n", startTimeStamp)
  215. endTimeStamp, err := strconv.ParseFloat(event["Timestamp"], 64) // OK
  216. if err != nil {
  217. fmt.Printf("endTimeStamp转换出错: %v\n", err)
  218. return
  219. }
  220. fmt.Printf("endTimeStamp=%f\n", endTimeStamp)
  221. durationTime := time.Duration(endTimeStamp-startTimeStamp) * time.Second
  222. fmt.Println("durationTime=", durationTime)
  223. // 删除记录时间
  224. // delete(TimestampList, event["Uniqueid"])
  225. // * ===================================================================================== */
  226. // 判断呼叫状态,为 ANSWER 时才推送,否则见以上推送 Outgoing Call - Unattended 或 Incoming Call - Missed
  227. if DialStatusList[event["Linkedid"]] == event["DialStatus"] {
  228. // Outgoing Call - Ended
  229. if event["Context"] == "macro-trunkdial-failover" {
  230. // 获取时间
  231. // durationTime := getDuration(event["Uniqueid"], event["Timestamp"])
  232. durationTime := getDuration(event["Linkedid"], event["Timestamp"])
  233. // /* ===================测试用 ============================================================
  234. // startTime, _ := time.Parse("2006-01-02 15:04:05", TimestampList[event["Uniqueid"]]) // error 1734328213.774410 => 0001-01-01 00:00:00 +0000 UTC
  235. // startTime := StartTimeList[event["Uniqueid"]]
  236. // startTime := StartTimeList[event["Uniqueid"]].Format("2006-01-02 15:04:09") // 存储从string 改为 time.Time
  237. startTime := StartTimeList[event["Linkedid"]].Format("2006-01-02 15:04:09") // 存储从string 改为 time.Time
  238. fmt.Println("startTime: ", startTime)
  239. // durationTime002 := getDuration002(startTime)
  240. // durationTime002 := time.Now().Sub(StartTimeList[event["Uniqueid"]]) // ok durationTime002: 7.78408849s // should use time.Since instead of time.Now().Sub (S1012)
  241. // durationTime002 := time.Since(StartTimeList[event["Uniqueid"]]) // ok durationTime002: 11.611233458s
  242. // fmt.Println("durationTime002: ", durationTime002)
  243. // * ===================================================================================== */
  244. // 删除记录时间
  245. delete(StartTimeList, event["Linkedid"])
  246. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=dailed&state=ended&id=10030&from=123456789&to=12300000001&start_time=2024-12-04 11:32:15&duration=325
  247. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dailed&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)
  248. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dailed&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDNum"], startTime, durationTime)
  249. if zohoUser != "" {
  250. getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  251. }
  252. fmt.Println("getURL = ", getURL)
  253. go httpclient.ZohoGet(getURL)
  254. // Incoming Call - Ended
  255. // if event["Context"] == "macro-stdexten" { // Context:DialPlan1
  256. } else if event["Context"] == "macro-stdexten" || event["Context"] == "macro-stdexten-withoutvm" { // 开启语音留言:macro-stdexten 关闭语音留言:macro-stdexten-withoutvm
  257. // if event["Context"] != "macro-trunkdial-failover" {
  258. // 还需优化判断,开启语音留言时,主叫挂断才是 macro-stdexten , 被叫挂断是 DialPlan1
  259. // 关闭语音留言时,主叫挂断才是 macro-stdexten-withoutvm , 被叫挂断是 DialPlan1
  260. // 如果 Outgoing Call 只会是 macro-trunkdial-failover 的话,那么和以下判断换一下,else 不判断,都为 Incoming Call 处理
  261. // 获取时间
  262. // durationTime := getDuration(event["Uniqueid"], event["Timestamp"])
  263. // startTime := StartTimeList[event["Uniqueid"]].Format("2006-01-02 15:04:09") // 存储从string 改为 time.Time
  264. durationTime := getDuration(event["Linkedid"], event["Timestamp"])
  265. startTime := StartTimeList[event["Linkedid"]].Format("2006-01-02 15:04:09") // 存储从string 改为 time.Time
  266. fmt.Println("startTime: ", startTime)
  267. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=received&state=ended&id=100&from=12300000001&to=123456789&start_time=2024-12-04 10:32:10&duration=223
  268. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)
  269. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDName"], startTime, durationTime)
  270. if zohoUser != "" {
  271. getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  272. }
  273. fmt.Println("getURL = ", getURL)
  274. go httpclient.ZohoGet(getURL)
  275. }
  276. }
  277. }
  278. // fmt.Println("getURL = ", getURL)
  279. // 测试验证下上面有没有删除,以防TimestampList越来越大
  280. for k, v := range TimestampList {
  281. fmt.Printf("===Linkedid:%s Timestamp:%s===\n", k, v)
  282. }
  283. }
  284. // 使用事件中event["Timestamp"]的值计算时间间隔
  285. // func getDuration(uniqueid string, timeStamp string) int {
  286. func getDuration(linkedid string, timeStamp string) int { // 都改为 Linkedid
  287. fmt.Println("startTimeStamp Str: ", TimestampList[linkedid])
  288. if TimestampList[linkedid] == "" || timeStamp == "" {
  289. fmt.Printf("linkedid 或 timeStamp 为空\n")
  290. return 9999
  291. }
  292. startTimeStamp, err := strconv.ParseFloat(TimestampList[linkedid], 64)
  293. if err != nil {
  294. fmt.Printf("startTimeStamp转换出错: %v\n", err)
  295. return 9999
  296. }
  297. fmt.Printf("startTimeStamp=%f\n", startTimeStamp)
  298. endTimeStamp, err := strconv.ParseFloat(timeStamp, 64)
  299. if err != nil {
  300. fmt.Printf("endTimeStamp转换出错: %v\n", err)
  301. return 9999
  302. }
  303. fmt.Printf("endTimeStamp=%f\n", endTimeStamp)
  304. durationTime := time.Duration(endTimeStamp-startTimeStamp) * time.Second
  305. // fmt.Println("durationTime=", durationTime) // durationTime= 35s
  306. // fmt.Printf("durationTime=%d\n", durationTime) // durationTime=35000000000
  307. // fmt.Printf("durationTime=%d\n", durationTime.Seconds()) // durationTime=%!d(float64=35)
  308. // fmt.Printf("durationTime=%f\n", durationTime.Seconds()) // durationTime=35.000000
  309. fmt.Printf("durationTime=%d\n", int(durationTime.Seconds())) // durationTime=35
  310. // durationTime001 := time.Duration(endTimeStamp - startTimeStamp)
  311. // fmt.Println("durationTime001=", durationTime001) // durationTime001= 35ns
  312. // durationTime003 := time.Duration(endTimeStamp - startTimeStamp).Seconds()
  313. // fmt.Println("durationTime003=", durationTime003) // durationTime003= 3.5e-08
  314. // 删除记录时间
  315. delete(TimestampList, linkedid)
  316. // return durationTime
  317. return int(durationTime.Seconds())
  318. }
  319. // // 程序中取时间计算间隔多少秒
  320. // func getDuration002(startTime string) time.Duration {
  321. // // durationTime := endTime.Sub(startTime)
  322. // startTime002, err := time.Parse("2006-01-02 15:04:05", startTime)
  323. // if err != nil {
  324. // fmt.Println("Error parsing time:", err)
  325. // return 0
  326. // }
  327. // durationTime := time.Now().Sub(startTime002)
  328. // return durationTime
  329. // }
  330. // @tags PBX-zoho
  331. // @Summary 刷新token
  332. // @Description 刷新token
  333. // @Security ZohoToken
  334. // @Accept json
  335. // @Produce json
  336. // @Router /api/zoho/refresh-token [post]
  337. func RefreshToken() {
  338. fmt.Printf("RefreshToken ............\n")
  339. // 获取配置文件信息
  340. // confPath := "/etc/asterisk/vtiger_api.conf"
  341. confPath := "/etc/asterisk/crm_api.conf"
  342. cfg, err := ini.Load(confPath)
  343. if err != nil {
  344. lfshook.NewLogger().Error(err)
  345. return
  346. }
  347. ZohoAuthUrl := cfg.Section("general").Key("zohoAuthUrl").String()
  348. ZohoRefreshToken := cfg.Section("general").Key("zohoRefreshToken").String()
  349. ZohoClientId := cfg.Section("general").Key("zohoClientId").String()
  350. ZohoClientSecret := cfg.Section("general").Key("zohoClientSecret").String()
  351. if ZohoAuthUrl == "" || ZohoRefreshToken == "" || ZohoClientId == "" || ZohoClientSecret == "" {
  352. lfshook.NewLogger().Error("/etc/asterisk/crm_api.conf not set zohoAuthUrl or zohoRefreshToken or zohoClientId or zohoClientSecret")
  353. return
  354. }
  355. // 创建请求
  356. // https://accounts.zoho.com/oauth/v2/token?refresh_token=1004.86c8c0e3db7bfe9133598825bef28eb9.17a82a3bf3e675c504f478c1b0b5c456
  357. // &client_id=1004.LWJCJZD5O9DB6SZLL5YJEWHT7LH0BV&client_secret=fc3aef43dc58af8a49d3ed597710924200b03f74d0&grant_type=refresh_token
  358. getURL := fmt.Sprintf("%s/oauth/v2/token?refresh_token=%s&client_id=%s&client_secret=%s&grant_type=refresh_token", ZohoAuthUrl, ZohoRefreshToken, ZohoClientId, ZohoClientSecret)
  359. fmt.Printf("getURL = %s\n", getURL)
  360. // data := httpRequest(ctx, "POST", getURL)
  361. // /* =====================================================================================
  362. req, err := http.NewRequest("POST", getURL, nil)
  363. if err != nil {
  364. fmt.Println("创建请求时发生错误:", err)
  365. return
  366. }
  367. // 创建HTTP客户端
  368. client := &http.Client{}
  369. // req.Header.Set("Authorization", "Bearer "+accessToken) // 刷新token时不需要
  370. // 发送请求
  371. resp, err := client.Do(req)
  372. if err != nil {
  373. fmt.Println("发送请求时发生错误:", err)
  374. return
  375. }
  376. defer resp.Body.Close()
  377. // 读取请求后的响应
  378. data, err := ioutil.ReadAll(resp.Body)
  379. if err != nil {
  380. // 读取数据错误
  381. lfshook.NewLogger().Warn("ioutil ReadAll failed :", err.Error())
  382. // api.Error(ctx, http.StatusInternalServerError, err.Error())
  383. return
  384. }
  385. lfshook.NewLogger().Infof("data %+v", string(data))
  386. // * ===================================================================================== */
  387. refreshTokenData := RefreshTokenResp{}
  388. err = json.Unmarshal([]byte(data), &refreshTokenData)
  389. if err != nil {
  390. // 转换数据错误
  391. lfshook.NewLogger().Warn("json unmarshal failed :", err.Error())
  392. // api.Error(ctx, http.StatusInternalServerError, err.Error())
  393. return
  394. }
  395. // 将获取的 access_token 写入文件 crm_api.conf
  396. cfg.Section("general").Key("zohoAccessToken").SetValue(refreshTokenData.AccessToken)
  397. err = cfg.SaveTo(confPath)
  398. if err != nil {
  399. lfshook.NewLogger().Error(err)
  400. // api.Error(ctx, http.StatusInternalServerError, err.Error())
  401. return
  402. }
  403. // 打印请求后的响应
  404. fmt.Printf("data = %+v\n", string(data))
  405. // api.Success(ctx, string(data))
  406. // api.Success(ctx, refreshTokenData)
  407. // return
  408. }
  409. // 每隔55分钟刷新token
  410. func RefreshTokenTicker() {
  411. fmt.Printf("RefreshTokenTicker ............\n")
  412. ticker := time.NewTicker(55 * time.Minute)
  413. defer ticker.Stop()
  414. done := make(chan bool)
  415. // go func() { // 注释掉OK
  416. for {
  417. select {
  418. case <-done:
  419. return
  420. case t := <-ticker.C:
  421. fmt.Println("Tick at", t)
  422. RefreshToken()
  423. }
  424. }
  425. // }()
  426. }