talent_ks_auth.go 43 KB

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