talent_ks_auth.go 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240
  1. package youngee_talent_service
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/chromedp/chromedp"
  6. "github.com/gogf/gf/frame/g"
  7. "github.com/gogf/gf/net/ghttp"
  8. "github.com/gogf/gf/os/gtime"
  9. "github.com/gogf/gf/util/gconv"
  10. douyinUser "github.com/lin-jim-leon/douyin/open/user"
  11. "github.com/lin-jim-leon/kuaishou/open/merchant"
  12. "github.com/lin-jim-leon/kuaishou/open/user"
  13. "log"
  14. "strings"
  15. "time"
  16. "youngmini_server/app/model/youngee_talent_model"
  17. "youngmini_server/app/service/youngee_sectask_service"
  18. "youngmini_server/app/utils"
  19. )
  20. const (
  21. //快手电商
  22. ClientKey = "ks651333097154138217"
  23. ClientSecret = "dBt0rVRhTpUqcrOYGGpv0A"
  24. SignSecret = "bf6393dce0a2b669ee348bebb837b0da"
  25. //快手平台
  26. ClientKey1 = "ks671599294546520767"
  27. ClientSecret1 = "8VSrp3O09nunjLMXR1uotg"
  28. //SignSecret1 = "bf6393dce0a2b669ee348bebb837b0da"
  29. //抖音平台
  30. ClientKey2 = "awi77xl5kpl16hmi"
  31. ClientSecret2 = "7ce6d2531bd4489122d89658063fd76e"
  32. //SignSecret1 = "bf6393dce0a2b669ee348bebb837b0da"
  33. )
  34. // 清理上下文的函数,用于关闭浏览器和取消上下文
  35. func CleanupChromedpContext(cancel context.CancelFunc) {
  36. if cancel != nil {
  37. cancel()
  38. fmt.Println("Chromedp 上下文已关闭")
  39. }
  40. }
  41. func GetQrcode(r *ghttp.Request) *TalentHttpResult {
  42. //达人id获取
  43. tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  44. fmt.Println("tid:", tid, "err:", err)
  45. if err != nil {
  46. return &TalentHttpResult{Code: -1, Msg: "Get talent id failed"}
  47. }
  48. // 记录开始时间
  49. startTime := time.Now()
  50. // 创建一个新的上下文
  51. // 确保 chromedp 上下文已初始化
  52. //initChromedpContext()
  53. ctx, cancel := chromedp.NewContext(context.Background()) //每个请求有独立的上下文,而不是共享的
  54. fmt.Println("上下文初始化成功")
  55. // 构建包含 tid 的 urlstr
  56. var urlstr string
  57. typePlatform := r.GetInt("platform_id")
  58. if typePlatform == 8 { //快手平台
  59. urlstr = fmt.Sprintf("https://open.kuaishou.com/oauth2/connect?state=%s&app_id=ks671599294546520767&redirect_uri=https://younggee.com/kuaishouVideo&scope=user_video_info,user_info&response_type=code", tid)
  60. } else if typePlatform == 2 { //抖音平台
  61. urlstr = fmt.Sprintf("https://open.douyin.com/platform/oauth/connect/?state=%s&client_key=awi77xl5kpl16hmi&response_type=code&scope=user_info,data.external.user,video.list.bind&redirect_uri=https://www.younggee.com/douyinauth", tid)
  62. } else {
  63. return &TalentHttpResult{Code: -1, Msg: "platform_id值不合法"}
  64. }
  65. // 执行任务
  66. //var buf []byte
  67. var text string
  68. var ok bool
  69. var tasks chromedp.Tasks
  70. if typePlatform == 2 { //抖音
  71. tasks = chromedp.Tasks{
  72. chromedp.Navigate(urlstr),
  73. // chromedp.WaitVisible(`#semiTabPanelqr > div > div > div.qr-container > img`, chromedp.ByQuery),
  74. chromedp.AttributeValue(`#semiTabPanelqr > div > div > div.qr-container > img`, "src", &text, &ok),
  75. }
  76. } else { //快手
  77. tasks = chromedp.Tasks{
  78. chromedp.Navigate(urlstr),
  79. // chromedp.WaitVisible(`body > div > div > div > div.qr-code-main > img:nth-child(1)`, chromedp.ByQuery),
  80. chromedp.AttributeValue(`body > div > div > div > div.qr-code-main > img:nth-child(1)`, "src", &text, &ok),
  81. }
  82. }
  83. //浏览器启动!
  84. err = chromedp.Run(ctx, tasks)
  85. if err != nil {
  86. log.Fatal(err)
  87. }
  88. println("text----->", text)
  89. println("ok----->", ok)
  90. println("url----->", urlstr)
  91. fmt.Println("代码运行时间:", time.Since(startTime))
  92. // 设置定时器,100秒后关闭上下文
  93. go func() {
  94. <-time.After(100 * time.Second)
  95. CleanupChromedpContext(cancel)
  96. }()
  97. return &TalentHttpResult{Code: 0, Msg: "success", Data: text}
  98. }
  99. func GetKsEcomQrcode(r *ghttp.Request) *TalentHttpResult {
  100. //达人id获取
  101. tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  102. fmt.Println("tid:", tid, "err:", err)
  103. if err != nil {
  104. return &TalentHttpResult{Code: -1, Msg: "Get talent id failed"}
  105. }
  106. // 记录开始时间
  107. startTime := time.Now()
  108. // 创建一个新的上下文
  109. ctx, cancel := chromedp.NewContext(context.Background())
  110. //ctx, cancel := chromedp.NewContext(context.Background(), chromedp.WithDebugf(log.Printf))
  111. // 设置定时器,100秒后关闭上下文
  112. //go func() {
  113. // <-time.After(100 * time.Second)
  114. // CleanupChromedpContext(cancel)
  115. //}()
  116. //需要访问的网址,无state,扫码后跳转到订购页面
  117. urlstr := fmt.Sprintf("https://login.kwaixiaodian.com/?biz=fuwu&redirect_url=https://fuwu.kwaixiaodian.com/new/detail?id=22328015871939")
  118. // 执行任务
  119. var text string
  120. var ok bool
  121. var tasks chromedp.Tasks
  122. //快手小店授权码
  123. tasks = chromedp.Tasks{
  124. chromedp.Navigate(urlstr),
  125. //点击出现二维码
  126. chromedp.Click(`#root > div > div.UqM2VqEDB3qdOFvSOHAB > div > div > div > div.container__content > div:nth-child(1) > div`),
  127. // 获取二维码
  128. chromedp.AttributeValue(`#root > div > div.UqM2VqEDB3qdOFvSOHAB > div > div > div > div.Kmu1OHb3un0JBPZDkGa8 > div.JAc4fjotOx_h8lOtGzuB > div.dIaAe1BsCdQL6GtURkNI > img`, "src", &text, &ok),
  129. }
  130. //浏览器启动!
  131. err = chromedp.Run(ctx, tasks)
  132. if err != nil {
  133. fmt.Println("errInfo---", err.Error())
  134. }
  135. fmt.Println("代码运行时间:", time.Since(startTime))
  136. // 返回二维码的操作已经完成,后续操作(go fun)在后台继续进行
  137. // 启动后台 goroutine 监听重定向并处理
  138. go HandleAfterRedirect(r, ctx, cancel)
  139. return &TalentHttpResult{Code: 0, Msg: "二维码已生成", Data: text}
  140. }
  141. // 此函数执行完毕后
  142. func HandleAfterRedirect(r *ghttp.Request, ctx context.Context, cancel context.CancelFunc) *TalentHttpResult {
  143. fmt.Println("HandleAfterRedirect-----")
  144. //达人id获取
  145. tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  146. fmt.Println("tid:", tid, "err:", err)
  147. var isChecked1, isChecked2 bool
  148. //var isChecked1 bool
  149. var currentURL string
  150. var subscribeURL string
  151. authURL := fmt.Sprintf("https://open.kwaixiaodian.com/oauth/authorize?app_id=ks651333097154138217&redirectUri=https://younggee.com/kuaishouauth&scope=merchant_distribution,merchant_refund,merchant_item,merchant_order,user_info,merchant_servicemarket,merchant_user,merchant_logistics&state=%s", tid)
  152. // 执行任务
  153. fmt.Println("扫码跳转成功,正在提交订单...")
  154. err = chromedp.Run(ctx, chromedp.Tasks{
  155. // 等待用户扫码并跳转后,点击“立即购买”按钮,在这识别用户是否扫码完成
  156. chromedp.WaitVisible(`#main_root > div > div.yPXHTHq9cx_6vEhWohw_ > div.Jb15b0XMeXvmyWfEfrvq > div.m5IIGVbmvqsfZdb00GFO > div.JktibAFTihy_wzOaJXHl > div.Cbz2c2xjrwvEPJnVK4iA > div.KY1LeQ_L_xVgT9RzkLow.cgxWbYdA4fs28QuNN36F > button`, chromedp.ByQuery),
  157. chromedp.Click(`#main_root > div > div.yPXHTHq9cx_6vEhWohw_ > div.Jb15b0XMeXvmyWfEfrvq > div.m5IIGVbmvqsfZdb00GFO > div.JktibAFTihy_wzOaJXHl > div.Cbz2c2xjrwvEPJnVK4iA > div.KY1LeQ_L_xVgT9RzkLow.cgxWbYdA4fs28QuNN36F > button`, chromedp.ByQuery),
  158. // 等待第一个 checkbox 元素可见
  159. chromedp.WaitVisible(`#app > div > section > main > div.cart-container > div.price-content > div.checkbox > label > span.ant-checkbox > input`, chromedp.ByQuery),
  160. // 检查第一个 checkbox 是否已选中
  161. chromedp.EvaluateAsDevTools(`document.querySelector('#app > div > section > main > div.cart-container > div.price-content > div.checkbox > label > span.ant-checkbox > input').checked`, &isChecked1),
  162. chromedp.Location(&subscribeURL),
  163. })
  164. if err != nil {
  165. log.Fatalf("任务1执行失败:%v", err)
  166. }
  167. fmt.Println("订阅页面---->", subscribeURL)
  168. if !isChecked1 {
  169. fmt.Println("第一个 Checkbox 未选中。现在选中...")
  170. err = chromedp.Run(ctx, chromedp.Click(`#app > div > section > main > div.cart-container > div.price-content > div.checkbox > label > span.ant-checkbox > input`, chromedp.ByQuery))
  171. fmt.Println("选中成功")
  172. if err != nil {
  173. log.Fatalf("点击第一个 checkbox 失败:%v", err)
  174. }
  175. } else {
  176. fmt.Println("第一个 Checkbox 已经选中。")
  177. }
  178. // 确认订单 拆分
  179. fmt.Println("这一步进行服务的订阅...")
  180. err = chromedp.Run(ctx, chromedp.Tasks{
  181. chromedp.Click(`#app > div > section > main > div.cart-container > div.price-content > div.checkout > button`, chromedp.ByQuery),
  182. chromedp.Navigate(authURL),
  183. chromedp.Location(&currentURL),
  184. })
  185. //出现点击服务订阅,失败的问题,等不到下一个页面的出现
  186. //// Step 1: 点击按钮
  187. //fmt.Println("1")
  188. //err = chromedp.Run(ctx, chromedp.Tasks{
  189. // chromedp.Click(`#app > div > section > main > div.cart-container > div.price-content > div.checkout > button`, chromedp.ByQuery), // 点击按钮
  190. //})
  191. //fmt.Println("2")
  192. //if err != nil {
  193. // log.Fatalf("获取 afterbuyURL 失败: %v", err)
  194. //}
  195. // Step 4: 跳转到授权页面
  196. //err = chromedp.Run(ctx, chromedp.WaitVisible(`#app > div > section > main > div.paid-container > div.title`, chromedp.ByQuery))
  197. //if err != nil {
  198. // log.Fatalf("跳转到授权页面失败:%v", err)
  199. //}
  200. //fmt.Println("3")
  201. // Step 4: 跳转到授权页面
  202. //err = chromedp.Run(ctx, chromedp.Navigate(authURL))
  203. //if err != nil {
  204. // log.Fatalf("跳转到授权页面失败:%v", err)
  205. //}
  206. // Step 5: 获取授权页面 URL
  207. err = chromedp.Run(ctx, chromedp.Location(&currentURL))
  208. if err != nil {
  209. log.Fatalf("获取 currentURL 失败:%v", err)
  210. }
  211. if err != nil {
  212. fmt.Println("提交订单失败---", err.Error())
  213. }
  214. fmt.Println("当前授权地址url---》:", currentURL)
  215. fmt.Println("服务的订阅成功...")
  216. //提交订单需要时间处理
  217. //time.Sleep(3 * time.Second)
  218. //跳转到授权页面
  219. //err = chromedp.Run(ctx, chromedp.Tasks{
  220. // chromedp.Navigate(authURL),
  221. // chromedp.Location(&currentURL),
  222. //})
  223. //期望含code
  224. //不管是否订购过 , 肯定会包含 ,需要手动点击则点击, 不需要手动点击直接授权成功
  225. if strings.Contains(currentURL, "https://open.kwaixiaodian.com/oauth/authorize") {
  226. log.Println("into https://open.kwaixiaodian.com/oauth/authorize")
  227. err = chromedp.Run(ctx, chromedp.WaitVisible(`#root > div > div > div > div > div.flex.f-jc-c.UcUNDIrRp1R3a9EnEbQE > div > div.f-1.f-fs-0.Zcms9k6vZGxKICWMIrdG > div.wNrvV7C_9L5FB2oxmyLe > div > div:nth-child(2) > label > span.ant-checkbox > input`, chromedp.ByQuery))
  228. if err != nil {
  229. log.Println("WaitVisible执行失败:%v", err)
  230. }
  231. log.Println("等待第二个 checkbox 元素可见")
  232. // 检查第二个 checkbox 获得选中情况
  233. err = chromedp.Run(ctx, chromedp.EvaluateAsDevTools(`document.querySelector('#root > div > div > div > div > div.flex.f-jc-c.UcUNDIrRp1R3a9EnEbQE > div > div.f-1.f-fs-0.Zcms9k6vZGxKICWMIrdG > div.wNrvV7C_9L5FB2oxmyLe > div > div:nth-child(2) > label > span.ant-checkbox > input').checked`, &isChecked2))
  234. if err != nil {
  235. log.Println("EvaluateAsDevTools执行失败:%v", err)
  236. }
  237. log.Println("检查第二个 checkbox 获得选中情况")
  238. // 如果第二个 checkbox 没有选中,则点击选中
  239. if !isChecked2 {
  240. //选中同意
  241. err = chromedp.Run(ctx, chromedp.Click(`#root > div > div > div > div > div.flex.f-jc-c.UcUNDIrRp1R3a9EnEbQE > div > div.f-1.f-fs-0.Zcms9k6vZGxKICWMIrdG > div.wNrvV7C_9L5FB2oxmyLe > div > div:nth-child(2) > label > span.ant-checkbox > input`, chromedp.ByQuery))
  242. //点击授权按钮,肯定重定向过去了
  243. } else {
  244. fmt.Println("第二个 Checkbox 已经选中。")
  245. }
  246. //点击后授权成功
  247. err = chromedp.Run(ctx, chromedp.Click(`#root > div > div > div > div > div.flex.f-jc-c.UcUNDIrRp1R3a9EnEbQE > div > div.f-1.f-fs-0.Zcms9k6vZGxKICWMIrdG > div.wNrvV7C_9L5FB2oxmyLe > button`, chromedp.ByQuery))
  248. //等待跳转并且授权
  249. time.Sleep(10 * time.Second)
  250. CleanupChromedpContext(cancel)
  251. fmt.Println("ok")
  252. }
  253. // 输出执行完成的日志
  254. fmt.Println("授权完成")
  255. return &TalentHttpResult{Code: 0, Msg: "已重定向到kuaishouauth接口", Data: nil}
  256. }
  257. // 检查数据库表中是否有达人对应的数据 且 token未过期
  258. func CheckAccount(r *ghttp.Request) *TalentHttpResult {
  259. fmt.Println("into check")
  260. //达人id获取
  261. tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  262. if err != nil {
  263. return &TalentHttpResult{Code: -1, Msg: "Get talent id failed"}
  264. }
  265. userInfo := &youngee_talent_model.KuaishouUserInfo{}
  266. err = g.DB().Model(userInfo).Where("talent_id", tid).Scan(&userInfo)
  267. fmt.Println("userInfo*********", userInfo)
  268. if err != nil {
  269. // 查询失败(未找到结果),返回失败结果
  270. return &TalentHttpResult{Code: -1, Msg: "Query failed", Data: nil}
  271. }
  272. //有查询结果,看是否accessToken是否有效
  273. key, err1 := g.DB().Model("platform_kuaishou_user_info").Fields("access_token").Where("talent_id = ?", tid).Value()
  274. if err1 != nil {
  275. return &TalentHttpResult{Code: -1, Msg: "query database fail"}
  276. }
  277. AccessToken := key.String()
  278. _, err2 := user.GetUserinfo(ClientKey, AccessToken)
  279. if err2 != nil {
  280. //前端接收code=-2表示token过期
  281. return &TalentHttpResult{Code: -2, Msg: "accessToken过期", Data: nil}
  282. }
  283. // 查询成功,返回成功结果和数据
  284. return &TalentHttpResult{Code: 0, Msg: "success", Data: userInfo}
  285. }
  286. // / 抖音二维码绑定,轮询此接口,
  287. //func CheckDyNewAccount(r *ghttp.Request) *TalentHttpResult {
  288. // //check到了更新时间在两秒内的插入的数据。则说明已绑定。弹窗消失。
  289. // tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  290. // redisDyBindStatusKey := fmt.Sprintf("Bind:%s", tid)
  291. // bindStatus, err := g.Redis().DoVar("GET", redisDyBindStatusKey)
  292. // if bindStatus.String() == "bound_to_other" {
  293. // return &TalentHttpResult{Code: -1, Msg: "此账号已被其他达人绑定", Data: nil}
  294. // }
  295. // if err != nil {
  296. // return &TalentHttpResult{Code: -1, Msg: "Get talent id failed"}
  297. // }
  298. // // 获取当前时间
  299. // currentTime := gtime.Now()
  300. // // 查询数据库中符合条件的所有记录
  301. // var userInfos []youngee_talent_model.KuaishouUserInfo
  302. // err = g.DB().Model("platform_kuaishou_user_info").
  303. // Where("talent_id = ?", tid).
  304. // Scan(&userInfos)
  305. // if err != nil {
  306. // return &TalentHttpResult{Code: -4, Msg: "Database query failed"}
  307. // }
  308. //
  309. // if len(userInfos) == 0 {
  310. // // 如果没有符合条件的数据,返回失败
  311. // return &TalentHttpResult{Code: -5, Msg: "No valid data found"}
  312. // }
  313. //
  314. // // 找到 CreateTime 最新的记录
  315. // latestUserInfo := userInfos[0]
  316. // for _, info := range userInfos[1:] {
  317. // if info.CreateTime.After(latestUserInfo.CreateTime) {
  318. // latestUserInfo = info
  319. // }
  320. // }
  321. //
  322. // // 计算创建时间与当前时间的差值
  323. // timeDiff := currentTime.Sub(latestUserInfo.CreateTime)
  324. // if timeDiff <= 3*time.Second {
  325. // return &TalentHttpResult{Code: 0, Msg: "success"}
  326. // }
  327. //
  328. // // 超过时间差,返回失败
  329. // return &TalentHttpResult{Code: -6, Msg: "Time difference exceeds 3 seconds"}
  330. //}
  331. // 用于轮询,检查数据库表中是否有达人对应的数据,有就删掉,/kuaishouath中会插入。
  332. func CheckNewAccount(r *ghttp.Request) *TalentHttpResult {
  333. //check到了更新时间在两秒内的插入的数据。则说明已绑定。弹窗消失。
  334. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  335. platformId := r.GetQueryInt("platform_id", 0)
  336. if platformId == 0 {
  337. return &TalentHttpResult{Code: -1, Msg: "参数格式有误", Data: nil}
  338. }
  339. if platformId == 4 || platformId == 8 || platformId == 2 {
  340. redisKsBindStatusKey := fmt.Sprintf("Bind:%s", tid)
  341. bindStatus, err := g.Redis().DoVar("GET", redisKsBindStatusKey)
  342. if bindStatus != nil && bindStatus.String() == "bound_to_other" {
  343. return &TalentHttpResult{Code: -1, Msg: "此快手账号已被其他达人绑定", Data: nil}
  344. }
  345. if err != nil {
  346. return &TalentHttpResult{Code: -3, Msg: "Get talent id failed"}
  347. }
  348. // 获取当前时间
  349. currentTime := gtime.Now()
  350. // 查询数据库中符合条件的所有记录
  351. var userInfos []youngee_talent_model.KuaishouUserInfo
  352. err = g.DB().Model("platform_kuaishou_user_info").
  353. Where("talent_id = ? AND platform_id=?", tid, platformId).
  354. Scan(&userInfos)
  355. if err != nil {
  356. return &TalentHttpResult{Code: -4, Msg: "Database query failed"}
  357. }
  358. //当前达人没有绑定过账号
  359. if len(userInfos) == 0 {
  360. // 如果没有符合条件的数据,返回失败
  361. // 如果没有符合条件的数据,返回继续轮询的提示
  362. return &TalentHttpResult{Code: -5, Msg: "没有数据,继续轮询"}
  363. }
  364. // 找到 CreateTime 最新的记录
  365. latestUserInfo := userInfos[0]
  366. for _, info := range userInfos[1:] {
  367. if info.CreateTime.After(latestUserInfo.CreateTime) {
  368. latestUserInfo = info
  369. }
  370. }
  371. // 计算创建时间与当前时间的差值
  372. timeDiff := currentTime.Sub(latestUserInfo.CreateTime)
  373. if timeDiff <= 5*time.Second {
  374. return &TalentHttpResult{Code: 0, Msg: "授权完成,数据已入库"}
  375. }
  376. // 超过时间差,返回失败
  377. return &TalentHttpResult{Code: -2, Msg: "数据还没进来,继续轮训"}
  378. } else {
  379. return &TalentHttpResult{Code: -2, Msg: "platform_id只能是2,4,8"}
  380. }
  381. }
  382. func CheckTokenExp(openId string, platformId int, talentId string) int {
  383. fmt.Println("into checktoken")
  384. //检查平台8
  385. if platformId == 8 {
  386. key, err := g.DB().Model("platform_kuaishou_user_info").Fields("access_token").Where("talent_id = ? & platform_id = ? & open_id = ? ", talentId, platformId, openId).Value()
  387. if err != nil {
  388. fmt.Println("query database fail")
  389. return -1
  390. }
  391. AccessToken := key.String()
  392. _, err = user.GetUserinfo(ClientKey1, AccessToken)
  393. if err != nil { //过期
  394. fmt.Println("平台accessToken过期")
  395. //前端接收code=-2表示token过期
  396. return 0
  397. } else {
  398. fmt.Println("平台AT未过期")
  399. return 1
  400. }
  401. //检查电商授权4
  402. } else {
  403. key, err := g.DB().Model("platform_kuaishou_user_info").Fields("access_token").Where("talent_id = ? & platform_id = ? & open_id = ? ", talentId, platformId, openId).Value()
  404. if err != nil {
  405. fmt.Println("query database fail")
  406. return 2
  407. }
  408. AccessToken := key.String()
  409. _, err = user.GetUserinfo(ClientKey, AccessToken)
  410. if err != nil { //过期
  411. //前端接收code=-2表示token过期
  412. fmt.Println("电商accessToken过期")
  413. return 3
  414. } else {
  415. fmt.Println("电商accessToken未过期")
  416. return 4
  417. }
  418. }
  419. }
  420. // func CheckTokenExp(r *ghttp.Request) *TalentHttpResult {
  421. // //达人id获取
  422. // tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  423. // //平台id获取
  424. // platformId := r.GetInt("platform_id")
  425. // //openId获取
  426. // openId := r.GetString("open_id")
  427. // //检查平台授权
  428. // if platformId == 8 {
  429. // key, err := g.DB().Model("platform_kuaishou_user_info").Fields("access_token").Where("talent_id = ? & platform_id = ? & open_id = ? ", tid, platformId, openId).Value()
  430. // if err != nil {
  431. // return &TalentHttpResult{Code: -1, Msg: "query database fail"}
  432. // }
  433. // AccessToken := key.String()
  434. // res_info1, err := user.GetUserinfo(ClientKey1, AccessToken)
  435. // if err != nil { //过期
  436. // //前端接收code=-2表示token过期
  437. // return &TalentHttpResult{Code: -2, Msg: "平台accessToken过期", Data: nil}
  438. // } else {
  439. // return &TalentHttpResult{Code: 0, Msg: "平台accessToken未过期", Data: res_info1}
  440. // }
  441. // //检查电商授权
  442. // } else {
  443. // key, err := g.DB().Model("platform_kuaishou_user_info").Fields("access_token").Where("talent_id = ? & platform_id = ? & open_id = ? ", tid, platformId, openId).Value()
  444. // if err != nil {
  445. // return &TalentHttpResult{Code: -1, Msg: "query database fail"}
  446. // }
  447. // AccessToken := key.String()
  448. // res_info, err := user.GetUserinfo(ClientKey, AccessToken)
  449. // if err != nil { //过期
  450. // //前端接收code=-2表示token过期
  451. // return &TalentHttpResult{Code: -2, Msg: "电商accessToken过期", Data: nil}
  452. // } else {
  453. // return &TalentHttpResult{Code: 0, Msg: "平台accessToken未过期", Data: res_info}
  454. // }
  455. // }
  456. //
  457. // if err != nil {
  458. // return &TalentHttpResult{Code: -3, Msg: "Get talent id failed"}
  459. // }
  460. // key, err1 := g.DB().Model("platform_kuaishou_user_info").Fields("access_token").Where("talent_id = ? & platform_id = ? & open_id = ? ", tid, platformId, openId).Value()
  461. // if err1 != nil {
  462. // return &TalentHttpResult{Code: -1, Msg: "query database fail"}
  463. // }
  464. // AccessToken := key.String()
  465. // res_info, err2 := user.GetUserinfo(ClientKey, AccessToken)
  466. // if err2 != nil {
  467. // //前端接收code=-2表示token过期
  468. // return &TalentHttpResult{Code: -2, Msg: "accessToken过期", Data: nil}
  469. // }
  470. // // 查询成功,返回成功结果和数据
  471. // return &TalentHttpResult{Code: 0, Msg: "success", Data: res_info}
  472. // }
  473. func AddWindowKuaishouList(r *ghttp.Request) *TalentHttpResult {
  474. // 定义用于存储查询结果的结构体切片
  475. var results []*youngee_talent_model.KuaishouUserInfo
  476. // 获取talent_id
  477. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  478. // 查询此达人下,platform_id 为 8 或 4 的所有数据,并将结果扫描到结构体切片中
  479. err := g.DB().Model(&youngee_talent_model.KuaishouUserInfo{}).
  480. Where("talent_id = ?", tid).
  481. Where("platform_id IN (?, ?)", 4, 8).
  482. Order("open_id ASC, platform_id DESC"). // 按 open_id 排序,确保每组的数据连续,并且 platform_id=4 的数据排在前面
  483. Scan(&results)
  484. if err != nil {
  485. return &TalentHttpResult{Code: 1, Msg: "查询失败", Data: nil}
  486. }
  487. // 创建一个 map,用于记录每个 open_id 对应的记录
  488. //key是openid,value是数组,从而实现一对多
  489. openIdMap := make(map[string][]*youngee_talent_model.KuaishouUserInfo)
  490. // 将查询结果按 open_id 分组
  491. for _, record := range results {
  492. openIdMap[record.OpenId] = append(openIdMap[record.OpenId], record)
  493. }
  494. //筛选出 open_id 对应两条数据且 platform_id = 4 的记录
  495. var resInfo []*youngee_talent_model.KuaishouUserInfo
  496. for _, records := range openIdMap {
  497. if len(records) == 2 { // 确保有两条数据,排除只有一个 platform_id 的情况
  498. for _, record := range records {
  499. if record.PlatformId == 4 { // 选取 platform_id = 4(电商) 的记录,含有粉丝数就好,因为需要加入橱窗
  500. resInfo = append(resInfo, record)
  501. break
  502. }
  503. }
  504. }
  505. }
  506. // 遍历 resInfo 检查过期和是否报名
  507. for _, record := range resInfo {
  508. // 调用 CheckKuaishouTokenExp 函数,检查 openId 是否过期
  509. expired := CheckKuaishouTokenExp(record.OpenId)
  510. fmt.Println()
  511. // 将过期检查结果赋值给 expired 属性 ,过期则不能被选中用于加入橱窗
  512. record.Expired = expired
  513. }
  514. return &TalentHttpResult{Code: 0, Msg: "快手列表展示成功", Data: resInfo}
  515. }
  516. func SignUpSecKuaishouList(r *ghttp.Request) *TalentHttpResult {
  517. selectionId := r.GetString("selection_id")
  518. //判断是否满足领样条件
  519. var freeStrategies []*youngee_talent_model.FreeStrategy
  520. err := g.DB().Model("free_strategy").Where("selection_id = ?", selectionId).Scan(&freeStrategies)
  521. var results []*youngee_talent_model.KuaishouUserInfo
  522. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  523. // 查询此达人下,platform_id 为 8 或 4 的所有数据,并将结果扫描到结构体切片中
  524. err = g.DB().Model(&youngee_talent_model.KuaishouUserInfo{}).
  525. Where("talent_id = ?", tid).
  526. Where("platform_id IN (?, ?)", 4, 8).
  527. Order("open_id ASC, platform_id DESC"). // 按 open_id 排序,确保每组的数据连续,并且 platform_id=4 的数据排在前面
  528. Scan(&results)
  529. if err != nil {
  530. return &TalentHttpResult{Code: 1, Msg: "查询失败", Data: nil}
  531. }
  532. // 创建一个 map,用于记录每个 open_id 对应的记录
  533. //key是openid,value是数组,从而实现一对多
  534. openIdMap := make(map[string][]*youngee_talent_model.KuaishouUserInfo)
  535. // 将查询结果按 open_id 分组
  536. for _, record := range results {
  537. openIdMap[record.OpenId] = append(openIdMap[record.OpenId], record)
  538. }
  539. // 筛选出 open_id 对应两条数据且 platform_id = 4 的记录
  540. var resInfo []*youngee_talent_model.KuaishouUserInfo
  541. for _, records := range openIdMap {
  542. if len(records) == 2 { // 确保有两条数据,排除只有一个 platform_id 的情况
  543. for _, record := range records {
  544. if record.PlatformId == 4 { // 选取 platform_id = 4(电商) 的记录,含有粉丝数就好,因为需要加入橱窗
  545. resInfo = append(resInfo, record)
  546. break
  547. }
  548. }
  549. }
  550. }
  551. // 遍历 resInfo 检查过期、是否报名、是否满足领养条件
  552. for _, record := range resInfo {
  553. // 调用 CheckKuaishouTokenExp 函数,检查 openId 是否过期
  554. expired := CheckKuaishouTokenExp(record.OpenId)
  555. // 将过期检查结果赋值给 expired 属性 ,过期则不能被选中用于加入橱窗
  556. record.Expired = expired
  557. //是否报名
  558. isSignResult, err := g.DB().Model("younggee_sec_task_info").Where("selection_id=? AND open_id=? AND talent_id=? AND sample_mode=?", selectionId, record.OpenId, tid, 1).One()
  559. // 根据查询结果设置 IsSign 属性
  560. if err != nil || isSignResult.IsEmpty() {
  561. record.IsSign = 0 // 没有查到数据,设置为 0
  562. } else {
  563. record.IsSign = 1 // 查到数据,设置为 1
  564. }
  565. //
  566. fanNum := record.Fan
  567. fmt.Println("我的粉丝数", fanNum)
  568. saleNum30 := record.SaleNum30day
  569. for _, strategy := range freeStrategies {
  570. // 判断粉丝数是否满足当前策略的要求
  571. if fanNum >= strategy.FollowersLow && saleNum30 >= strategy.SaleNum {
  572. // 如果粉丝数满足策略的范围,设置 is_fit 为 1
  573. record.IsOk = 1
  574. break
  575. } else {
  576. // 否则设置 is_fit 为 0
  577. record.IsOk = 0
  578. }
  579. }
  580. }
  581. return &TalentHttpResult{Code: 0, Msg: "列表展示成功", Data: resInfo}
  582. }
  583. // 只有绑定两个快手,且快手电商没有过期,才能访问到这
  584. func AddWindowWithKsAccount(r *ghttp.Request) *TalentHttpResult {
  585. // 获取talent_id
  586. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  587. var signSecTaskReq *youngee_talent_model.SignSecTaskFromWindowReq
  588. err := r.ParseForm(&signSecTaskReq)
  589. if err != nil {
  590. return &TalentHttpResult{Code: -1, Msg: "POST参数解析失败", Data: err.Error()}
  591. }
  592. value, err := g.DB().Model("platform_kuaishou_user_info").Fields("access_token").Where("talent_id=? AND open_id = ? AND platform_id = 4 ", tid, signSecTaskReq.OpenId).Value()
  593. if err != nil {
  594. fmt.Println("query db fail")
  595. }
  596. accessToken := value.String()
  597. fmt.Println("access_token:--->", accessToken)
  598. pIdSlice := []string{signSecTaskReq.KSProductId}
  599. httpResult := youngee_sectask_service.IsCreateSecTask(r)
  600. fmt.Println("httpResult--->", httpResult)
  601. if httpResult.Code == 1 { //存在报名信息,仅添加橱窗
  602. fmt.Println("大人id", tid)
  603. fmt.Println("accessToken--->", accessToken)
  604. _, err := merchant.AddItemsToShelf(ClientKey, SignSecret, accessToken, pIdSlice)
  605. if err != nil {
  606. //表示添加失敗,沒有開通
  607. fmt.Println("假如橱窗错误信息为---", err.Error())
  608. return &TalentHttpResult{Code: -1, Msg: "存在报名信息,快手未開通橱窗、商品不存在或已下线", Data: err.Error()}
  609. }
  610. // 查询成功,返回成功结果和数据
  611. return &TalentHttpResult{Code: 0, Msg: "无需创建任务,加入橱窗成功", Data: nil}
  612. } else { //不存在报名信息
  613. //创建并插入报名信息
  614. code := youngee_sectask_service.SignUpSecTaskFromWindow(r).Code
  615. fmt.Println("滴滴答答啦放假啦", code)
  616. if code != 0 {
  617. return &TalentHttpResult{Code: -1, Msg: "创建报名信息失败", Data: nil}
  618. }
  619. //加入橱窗
  620. _, err := merchant.AddItemsToShelf(ClientKey, SignSecret, accessToken, pIdSlice)
  621. if err != nil {
  622. //表示添加失敗,沒有開通
  623. return &TalentHttpResult{Code: -1, Msg: "不存在报名信息,快手未開通橱窗、商品不存在或已下线", Data: err.Error()}
  624. }
  625. //报名人数加一
  626. _, err = g.DB().Model("younggee_selection_info").
  627. Where("selection_id=?", signSecTaskReq.SelectionId).
  628. Increment("enroll_num", 1)
  629. if err != nil {
  630. // 错误处理
  631. fmt.Println(err.Error())
  632. }
  633. return &TalentHttpResult{Code: 0, Msg: "创建了任务,加入橱窗成功", Data: nil}
  634. }
  635. }
  636. func AddWindow(r *ghttp.Request) *TalentHttpResult {
  637. pId := r.GetString("product_id")
  638. //通过pId获取kuaishou_product_id
  639. pIdSlice := []string{pId}
  640. //达人id获取
  641. tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  642. //加入橱窗-条件不满足的快手账号不能被选中
  643. //条件1. 没有开通橱窗
  644. //判断此快手账号是否绑定了两
  645. openId := r.GetString("open_id")
  646. // 执行数据库查询
  647. count, err := g.DB().Model("platform_kuaishou_user_info").
  648. Where("talent_id = ? AND open_id = ?", tid, openId).
  649. Count()
  650. if err != nil {
  651. // 处理错误
  652. return &TalentHttpResult{Code: -4, Msg: "出错了"}
  653. }
  654. if count != 2 {
  655. return &TalentHttpResult{Code: -5, Msg: "达人需要授权两个码"}
  656. }
  657. if err != nil {
  658. return &TalentHttpResult{Code: -1, Msg: "Get talent id failed"}
  659. }
  660. key, err := g.DB().Model("platform_kuaishou_user_info").Fields("access_token").Where("talent_id = ?", tid).Value()
  661. if err != nil {
  662. return &TalentHttpResult{Code: -2, Msg: "query database fail"}
  663. }
  664. AccessToken := key.String()
  665. res_info, err := merchant.AddItemsToShelf(ClientKey, SignSecret, AccessToken, pIdSlice)
  666. if err != nil {
  667. //前端接收code=-3表示添加失敗,沒有開通
  668. return &TalentHttpResult{Code: -3, Msg: "未開通、商品不存在或已下线", Data: nil}
  669. }
  670. // 查询成功,返回成功结果和数据
  671. return &TalentHttpResult{Code: 0, Msg: "加入橱窗成功", Data: res_info}
  672. }
  673. func GetKuaishouFansNum(r *ghttp.Request) *TalentHttpResult {
  674. //达人id获取
  675. tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  676. fmt.Println("********&&&&&&&&&&,tid", tid)
  677. if err != nil {
  678. return &TalentHttpResult{Code: -1, Msg: "Get talent id failed"}
  679. }
  680. key, err1 := g.DB().Model("platform_kuaishou_user_info").Fields("access_token").Where("talent_id = ? ", tid).Value()
  681. if err1 != nil {
  682. return &TalentHttpResult{Code: -2, Msg: "query database fail"}
  683. }
  684. AccessToken := key.String()
  685. res_user, err2 := user.GetUserinfo(ClientKey, AccessToken)
  686. if err2 != nil {
  687. //前端接收code=-3表示添加失敗,沒有開通
  688. return &TalentHttpResult{Code: -3, Msg: "获取快手用户信息出错", Data: nil}
  689. }
  690. // 查询成功,返回成功结果和数据
  691. return &TalentHttpResult{Code: 0, Msg: "获取快手用户信息成功", Data: res_user.Data}
  692. }
  693. func QuerySalesFor30Days(r *ghttp.Request) *TalentHttpResult {
  694. fmt.Println("into querySalesFor30Days")
  695. ClientKey := "ks651333097154138217"
  696. //ClientSecret := "dBt0rVRhTpUqcrOYGGpv0A"
  697. SignSecret := "bf6393dce0a2b669ee348bebb837b0da"
  698. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  699. // 创建一个 KuaishouUserInfo 结构体的实例
  700. userInfo := &youngee_talent_model.KuaishouUserInfo{}
  701. // 查询数据库中的 access_token 字段
  702. // 使用 g.DB() 获取数据库连接,并执行查询
  703. key, err := g.DB().Model(userInfo).Fields("access_token").Where("talent_id = ?", tid).Value()
  704. AccessToken := key.String()
  705. if err != nil {
  706. // 处理错误
  707. fmt.Println("Error querying access_token:", err)
  708. }
  709. // 输出查询到的 access_token 值
  710. fmt.Println("Access Token:", AccessToken)
  711. // 获取当前时间的时间戳(毫秒)
  712. currentTime := time.Now().UnixNano() / int64(time.Millisecond)
  713. // 30天前的时间戳(毫秒)
  714. beginTime30DaysAgo := currentTime - 30*24*60*60*1000
  715. // 定义每段查询的天数
  716. intervalDays := 7
  717. intervalMillis := int64(intervalDays * 24 * 60 * 60 * 1000)
  718. // 初始化 beginTime 和 endTime
  719. beginTime := beginTime30DaysAgo
  720. endTime := beginTime + intervalMillis
  721. saleNum := 0 //30天总销量
  722. // 循环查询,先处理四个7天的时间段
  723. for i := 0; i < 4; i++ {
  724. // 调整 endTime,确保不会超过当前时间
  725. if endTime > currentTime {
  726. endTime = currentTime
  727. }
  728. saleNum += GetSaleNumByDayInterval(ClientKey, SignSecret, AccessToken, beginTime, endTime)
  729. // 更新时间段
  730. beginTime = endTime
  731. endTime = beginTime + intervalMillis
  732. }
  733. // 最后处理剩余的2天时间段
  734. endTime = currentTime
  735. saleNum += GetSaleNumByDayInterval(ClientKey, SignSecret, AccessToken, beginTime, endTime)
  736. // 查询成功,返回成功结果和数据
  737. return &TalentHttpResult{Code: 0, Msg: "获取30天销售量成功", Data: saleNum}
  738. }
  739. func QueryOkSaleNum(r *ghttp.Request) *TalentHttpResult {
  740. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  741. openID := r.GetString("open_id")
  742. // 创建一个 KuaishouUserInfo 结构体的实例
  743. userInfo := &youngee_talent_model.KuaishouUserInfo{}
  744. // 查询数据库中的 access_token 字段
  745. // 使用 g.DB() 获取数据库连接,并执行查询
  746. key, err := g.DB().Model(userInfo).Fields("access_token").Where("talent_id = ? AND open_id= ? AND platform_id = ?", tid, openID, 4).Value()
  747. AccessToken := key.String()
  748. if err != nil {
  749. // 处理错误
  750. fmt.Println("Error querying access_token:", err)
  751. }
  752. if key == nil {
  753. // 处理错误
  754. fmt.Println("can not find talentId's bindinfo :", err)
  755. }
  756. //循环使用接口
  757. //
  758. // 获取当前时间的时间戳(毫秒)
  759. currentTime := time.Now().UnixNano() / int64(time.Millisecond)
  760. // 90天前的时间戳(毫秒)
  761. beginTime90DaysAgo := currentTime - 90*24*60*60*1000
  762. // 定义每段查询的天数
  763. intervalDays := 7
  764. intervalMillis := int64(intervalDays * 24 * 60 * 60 * 1000)
  765. // 初始化 beginTime 和 endTime
  766. beginTime := beginTime90DaysAgo
  767. endTime := beginTime + intervalMillis
  768. saleNum := 0 //90天总销量
  769. // 循环查询,先处理四个7天的时间段
  770. for i := 0; i < 12; i++ {
  771. // 调整 endTime,确保不会超过当前时间
  772. if endTime > currentTime {
  773. endTime = currentTime
  774. }
  775. saleNum += GetSaleNumByDayInterval_Ok(ClientKey, SignSecret, AccessToken, beginTime, endTime)
  776. // 更新时间段
  777. beginTime = endTime
  778. endTime = beginTime + intervalMillis
  779. }
  780. // 最后处理剩余的6天时间段
  781. endTime = currentTime
  782. saleNum += GetSaleNumByDayInterval_Ok(ClientKey, SignSecret, AccessToken, beginTime, endTime)
  783. // 查询成功,返回成功结果和数据
  784. return &TalentHttpResult{Code: 0, Msg: "获取90天销售量成功", Data: saleNum}
  785. }
  786. //func VideoCount(r *ghttp.Request) *TalentHttpResult {
  787. // tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  788. // // 创建一个 KuaishouUserInfo 结构体的实例
  789. // userInfo := &youngee_talent_model.KuaishouUserInfo{}
  790. //
  791. // // 查询数据库中的 access_token 字段
  792. // // 使用 g.DB() 获取数据库连接,并执行查询
  793. // key, err := g.DB().Model(userInfo).Fields("access_token").Where("talent_id = ? AND platform_id = ?", tid, 8).Value()
  794. // AccessToken := key.String()
  795. // if err != nil {
  796. // // 处理错误
  797. // fmt.Println("Error querying access_token:", err)
  798. // }
  799. // if key == nil {
  800. // // 处理错误
  801. // fmt.Println("can not find talentId's bindinfo :", err)
  802. // }
  803. //
  804. // count, err := GetVideoCount(ClientKey1, AccessToken)
  805. // return &TalentHttpResult{Code: 0, Msg: "获取总作品数成功", Data: count}
  806. //}
  807. //
  808. //func LikeCount(r *ghttp.Request) *TalentHttpResult {
  809. // tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  810. // // 创建一个 KuaishouUserInfo 结构体的实例
  811. // userInfo := &youngee_talent_model.KuaishouUserInfo{}
  812. //
  813. // // 查询数据库中的 access_token 字段
  814. // // 使用 g.DB() 获取数据库连接,并执行查询
  815. // key, err := g.DB().Model(userInfo).Fields("access_token").Where("talent_id = ? AND platform_id = ?", tid, 8).Value()
  816. // AccessToken := key.String()
  817. // if err != nil {
  818. // // 处理错误
  819. // fmt.Println("Error querying access_token:", err)
  820. // }
  821. // if key == nil {
  822. // // 处理错误
  823. // fmt.Println("can not find talentId's bindinfo :", err)
  824. // }
  825. // count, err := GetLikeCount(ClientKey1, AccessToken)
  826. // return &TalentHttpResult{Code: 0, Msg: "获取总点赞数成功", Data: count}
  827. //}
  828. // 获取用户快手平台账号列表
  829. func GetKuaishouList(r *ghttp.Request) *TalentHttpResult {
  830. // 从 session 中获取 talent_id
  831. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  832. userInfo := &youngee_talent_model.KuaishouUserInfo{}
  833. // 查询 platformId 为 8 或 4 的所有数据
  834. results, err := g.DB().Model(userInfo).Where("talent_id = ?", tid).
  835. Where("platform_id IN (?, ?)", 4, 8).
  836. Order("platform_Id DESC").
  837. All()
  838. if err != nil {
  839. fmt.Println("Error querying access_token:", err)
  840. return &TalentHttpResult{Code: -1, Msg: "查询出错", Data: nil}
  841. }
  842. // 检查查询结果是否为空
  843. if len(results) == 0 {
  844. return &TalentHttpResult{Code: -2, Msg: "此达人无快手账号绑定", Data: nil}
  845. }
  846. // 使用集合来存储唯一的 open_id,并计算不同的 open_id 的个数
  847. openIDSet := make(map[string]struct{})
  848. //key--openId value--对应的信息
  849. userInfoMap := make(map[string]*youngee_talent_model.KuaishouUserInfo)
  850. for _, record := range results.List() {
  851. openID := gconv.String(record["open_id"])
  852. platformID := record["platform_id"] //int类型
  853. status := 0 //初始化
  854. //检查 userInfoMap 中是否已经存在 openID
  855. //肯定会先处理8,所以遇到重复情况肯定是两个都授权了
  856. _, exists := userInfoMap[openID]
  857. if exists {
  858. status = 1 //同时授权了两个码
  859. userInfoMap[openID] = &youngee_talent_model.KuaishouUserInfo{
  860. OpenId: openID,
  861. HeadUri: gconv.String(record["head_uri"]),
  862. NickName: gconv.String(record["nick_name"]),
  863. // 添加其他需要的字段
  864. Fan: gconv.Int(record["fan"]),
  865. //这两个值默认为0
  866. LikeNum: gconv.Int(record["like_num"]),
  867. VideoNum: gconv.Int(record["video_num"]),
  868. Status: status,
  869. }
  870. }
  871. //若同时有8和4的平台。处理了8就不会处理4了
  872. if !exists {
  873. //只有一个且为4
  874. if platformID == 4 {
  875. status = 2 //仅授权了电商
  876. } else {
  877. status = 3 //仅授权了平台
  878. }
  879. openIDSet[openID] = struct{}{}
  880. // 根据 platformID 赋值
  881. userInfoMap[openID] = &youngee_talent_model.KuaishouUserInfo{
  882. OpenId: openID,
  883. HeadUri: gconv.String(record["head_uri"]),
  884. NickName: gconv.String(record["nick_name"]),
  885. Skill: gconv.String(record["skill"]),
  886. Gender: gconv.String(record["gender"]),
  887. // 添加其他需要的字段
  888. Fan: gconv.Int(record["fan"]),
  889. //这两个值默认为0
  890. LikeNum: gconv.Int(record["like_num"]),
  891. VideoNum: gconv.Int(record["video_num"]),
  892. Status: status,
  893. }
  894. }
  895. }
  896. // 构建 UserInfo 列表 参数分别表示初始长度和容量
  897. userInfoList := make([]*youngee_talent_model.KuaishouUserInfo, 0, len(userInfoMap))
  898. for _, info := range userInfoMap {
  899. expStatus := CheckKuaishouTokenExp(info.OpenId)
  900. info.Status = expStatus
  901. //将 info 添加到 userInfoList 列表的末尾。
  902. userInfoList = append(userInfoList, info)
  903. }
  904. // 计算不同的 open_id 的个数
  905. uniqueOpenIDCount := len(openIDSet)
  906. // 创建 KSListResult 变量并赋值
  907. ksListResult := &youngee_talent_model.KSListResult{
  908. Count: uniqueOpenIDCount,
  909. UserInfo: userInfoList,
  910. }
  911. // 返回结果
  912. return &TalentHttpResult{Code: 1, Msg: "返回快手列表成功", Data: ksListResult}
  913. }
  914. // 获取用户快手电商过期信息 肯定绑定两个码,因为只是用于加入橱窗---我只检查电商是否过期
  915. func CheckKuaishouTokenExp(openId string) int {
  916. fmt.Println("into checktoken")
  917. //一个openId同时对应了8和4,才进行过期检查,两个都检查,有一个过期则过期
  918. key, err := g.DB().Model("platform_kuaishou_user_info").Fields("access_token").Where("open_id = ? ", openId).Value()
  919. if err != nil {
  920. fmt.Println("query database fail")
  921. return -1
  922. }
  923. AccessToken := key.String()
  924. _, err = user.GetUserinfo(ClientKey, AccessToken)
  925. if err != nil { //过期
  926. fmt.Println("平台accessToken过期", err.Error())
  927. return 1
  928. } else {
  929. fmt.Println("未过期")
  930. return 0
  931. }
  932. }
  933. func CheckDouyinTokenExp(openId string) int {
  934. fmt.Println("into checktoken")
  935. key, err := g.DB().Model("platform_kuaishou_user_info").Fields("access_token").Where("open_id = ? ", openId).Value()
  936. if err != nil {
  937. fmt.Println("query database fail")
  938. return -1
  939. }
  940. AccessToken := key.String()
  941. _, err = douyinUser.GetUserInfo(openId, AccessToken)
  942. if err != nil { //过期
  943. fmt.Println("平台accessToken过期")
  944. return 1
  945. } else {
  946. fmt.Println("未过期")
  947. return 0
  948. }
  949. }
  950. func GetDouyinList(r *ghttp.Request) *TalentHttpResult {
  951. // 获取达人对应的平台为2的列表,含基本信息
  952. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  953. userInfo := &youngee_talent_model.KuaishouUserInfo{}
  954. results, err := g.DB().Model(userInfo).Where("talent_id = ? AND platform_Id = ? ", tid, 2).
  955. All()
  956. if err != nil {
  957. fmt.Println("Error querying ", err)
  958. return &TalentHttpResult{Code: 0, Msg: "查询抖音列表失败", Data: nil}
  959. }
  960. // 创建一个存储用户信息的切片
  961. UserInfoList := []*youngee_talent_model.KuaishouUserInfo{}
  962. // 遍历列表,判断是否过期并更新 Expired 属性
  963. for _, record := range results.List() {
  964. openID := gconv.String(record["open_id"])
  965. // 调用 CheckDouyinTokenExp 函数,获取过期状态 0/1
  966. expiredStatus := CheckDouyinTokenExp(openID)
  967. // 更新 record 中的 Expired 字段值
  968. record["Expired"] = expiredStatus
  969. err := gconv.Struct(record, userInfo)
  970. if err != nil {
  971. return nil
  972. } // 将 map 转换为 KuaishouUserInfo 结构体
  973. // 添加到用户信息列表
  974. UserInfoList = append(UserInfoList, userInfo)
  975. }
  976. // 返回 DYListResult 类型
  977. return &TalentHttpResult{Code: 1, Msg: "返回抖音列表成功", Data: &youngee_talent_model.DYListResult{
  978. Count: len(UserInfoList),
  979. UserInfo: UserInfoList,
  980. }}
  981. }
  982. func GetMyAccountList(r *ghttp.Request) *TalentHttpResult {
  983. // 获取达人对应的平台为2的列表,含基本信息
  984. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  985. pId := r.GetQueryInt("platform_id", 0)
  986. fmt.Println("PlatformId:", pId)
  987. if pId != 1 && pId != 3 && pId != 5 {
  988. return &TalentHttpResult{Code: -1, Msg: "platform_id无效"}
  989. }
  990. AccountList := []*youngee_talent_model.KuaishouUserInfo{}
  991. g.Model("platform_kuaishou_user_info").Where("talent_id=? AND platform_id=? AND is_delete = ?", tid, pId, 0).Scan(&AccountList)
  992. if len(AccountList) == 0 {
  993. return &TalentHttpResult{Code: 0, Msg: "无内容", Data: nil}
  994. }
  995. return &TalentHttpResult{Code: 1, Msg: "返回列表成功", Data: &youngee_talent_model.AccountListResult{
  996. Count: len(AccountList),
  997. UserInfo: AccountList,
  998. }}
  999. }
  1000. func QuerySalesFor90Days(r *ghttp.Request) *TalentHttpResult {
  1001. tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
  1002. // 创建一个 KuaishouUserInfo 结构体的实例
  1003. userInfo := &youngee_talent_model.KuaishouUserInfo{}
  1004. // 查询数据库中的 access_token 字段
  1005. // 使用 g.DB() 获取数据库连接,并执行查询
  1006. key, err := g.DB().Model(userInfo).Fields("access_token").Where("talent_id = ?", tid).Value()
  1007. AccessToken := key.String()
  1008. if err != nil {
  1009. // 处理错误
  1010. fmt.Println("Error querying access_token:", err)
  1011. }
  1012. if key == nil {
  1013. // 处理错误
  1014. fmt.Println("can not find talentId's bindinfo :", err)
  1015. }
  1016. //循环使用接口
  1017. //
  1018. // 获取当前时间的时间戳(毫秒)
  1019. currentTime := time.Now().UnixNano() / int64(time.Millisecond)
  1020. // 30天前的时间戳(毫秒)
  1021. beginTime90DaysAgo := currentTime - 90*24*60*60*1000
  1022. // 定义每段查询的天数
  1023. intervalDays := 7
  1024. intervalMillis := int64(intervalDays * 24 * 60 * 60 * 1000)
  1025. // 初始化 beginTime 和 endTime
  1026. beginTime := beginTime90DaysAgo
  1027. endTime := beginTime + intervalMillis
  1028. saleNum := 0 //90天总销量
  1029. // 循环查询,先处理四个7天的时间段
  1030. for i := 0; i < 12; i++ {
  1031. // 调整 endTime,确保不会超过当前时间
  1032. if endTime > currentTime {
  1033. endTime = currentTime
  1034. }
  1035. saleNum += GetSaleNumByDayInterval(ClientKey, SignSecret, AccessToken, beginTime, endTime)
  1036. // 更新时间段
  1037. beginTime = endTime
  1038. endTime = beginTime + intervalMillis
  1039. }
  1040. // 最后处理剩余的6天时间段
  1041. endTime = currentTime
  1042. saleNum += GetSaleNumByDayInterval(ClientKey, SignSecret, AccessToken, beginTime, endTime)
  1043. // 查询成功,返回成功结果和数据
  1044. return &TalentHttpResult{Code: 0, Msg: "获取30天销售量成功", Data: saleNum}
  1045. }
  1046. func GetSaleNumByDayInterval(ClientKey string, SignSecret string, AccessToken string, beginTime int64, endTime int64) int {
  1047. pageSize := 100
  1048. totalSaleNum := 0
  1049. // 定义要查询的订单状态
  1050. // [30:已付款] [50:已收货] [60:已结算] [80:已失效]
  1051. statuses := []int{30, 50, 60}
  1052. // 遍历所有订单状态并调用 Corderlist 函数
  1053. for _, status := range statuses {
  1054. // 初始化 pcursor
  1055. pcursor := ""
  1056. for {
  1057. // 调用 Corderlist 函数获取订单列表
  1058. response, err := merchant.Corderlist(ClientKey, SignSecret, AccessToken, status, pageSize, beginTime, endTime, pcursor)
  1059. fmt.Println("response********", response)
  1060. if err != nil {
  1061. fmt.Printf("Error calling Corderlist: %v\n", err)
  1062. break
  1063. }
  1064. // 检查响应代码
  1065. if response.Code != "1" {
  1066. fmt.Printf("Corderlist response error: %s\n", response.Msg)
  1067. break
  1068. }
  1069. // 累加订单中商品的数量
  1070. for _, order := range response.Data.OrderViews {
  1071. for _, product := range order.CPSOrderProductViews {
  1072. totalSaleNum += product.Num
  1073. }
  1074. }
  1075. // 检查分页指针 pcursor
  1076. //100个订单以内的情况
  1077. if response.Data.Cursor == "nomore" {
  1078. break
  1079. }
  1080. //大于等于100个订单
  1081. // 更新 pcursor 以获取下一页数据
  1082. pcursor = response.Data.Cursor
  1083. // 处理分页后的数据
  1084. // 如果 pcursor 不是 "nomore",我们需要累加最后一条订单的数量
  1085. if len(response.Data.OrderViews) > 0 {
  1086. lastOrder := response.Data.OrderViews[len(response.Data.OrderViews)-1]
  1087. if len(lastOrder.CPSOrderProductViews) > 0 {
  1088. lastProduct := lastOrder.CPSOrderProductViews[len(lastOrder.CPSOrderProductViews)-1]
  1089. totalSaleNum += lastProduct.Num
  1090. }
  1091. }
  1092. }
  1093. }
  1094. return totalSaleNum
  1095. }
  1096. func GetSaleNumByDayInterval_Ok(ClientKey string, SignSecret string, AccessToken string, beginTime int64, endTime int64) int {
  1097. pageSize := 100
  1098. totalSaleNum := 0
  1099. // 定义要查询的订单状态
  1100. // [30:已付款] [50:已收货] [60:已结算] [80:已失效]
  1101. statuses := []int{60}
  1102. // 遍历所有订单状态并调用 Corderlist 函数
  1103. for _, status := range statuses {
  1104. // 初始化 pcursor
  1105. pcursor := ""
  1106. for {
  1107. // 调用 Corderlist 函数获取订单列表
  1108. response, err := merchant.Corderlist(ClientKey, SignSecret, AccessToken, status, pageSize, beginTime, endTime, pcursor)
  1109. fmt.Println("response********", response)
  1110. if err != nil {
  1111. fmt.Printf("Error calling Corderlist: %v\n", err)
  1112. break
  1113. }
  1114. // 检查响应代码
  1115. if response.Code != "1" {
  1116. fmt.Printf("Corderlist response error: %s\n", response.Msg)
  1117. break
  1118. }
  1119. // 累加订单中商品的数量
  1120. for _, order := range response.Data.OrderViews {
  1121. for _, product := range order.CPSOrderProductViews {
  1122. totalSaleNum += product.Num
  1123. }
  1124. }
  1125. // 检查分页指针 pcursor
  1126. //100个订单以内的情况
  1127. if response.Data.Cursor == "nomore" {
  1128. break
  1129. }
  1130. //大于等于100个订单
  1131. // 更新 pcursor 以获取下一页数据
  1132. pcursor = response.Data.Cursor
  1133. // 处理分页后的数据
  1134. // 如果 pcursor 不是 "nomore",我们需要累加最后一条订单的数量
  1135. if len(response.Data.OrderViews) > 0 {
  1136. lastOrder := response.Data.OrderViews[len(response.Data.OrderViews)-1]
  1137. if len(lastOrder.CPSOrderProductViews) > 0 {
  1138. lastProduct := lastOrder.CPSOrderProductViews[len(lastOrder.CPSOrderProductViews)-1]
  1139. totalSaleNum += lastProduct.Num
  1140. }
  1141. }
  1142. }
  1143. }
  1144. return totalSaleNum
  1145. }