talent_ks_auth.go 46 KB

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