前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >抖音开放平台用户授权获取用户的粉丝统计和短视频数据

抖音开放平台用户授权获取用户的粉丝统计和短视频数据

原创
作者头像
悟空码字
修改于 2021-03-24 02:05:02
修改于 2021-03-24 02:05:02
6.5K00
代码可运行
举报
运行总次数:0
代码可运行

最近有朋友问起我有没有做过抖音开放平台,让我有了些思考,其实之前做过的。虽然抖音APP很火,但是毕竟不像微信开放平台那样,已沉淀多年,基本上每个API只要肯用心查找,网上都有很多资料可以参考。而抖音开放平台则不然,刚面世不久,资料比较少。即使对于一个开发人员来说,接入第三方接口都大同小异,不会太难,但我还是想把这些记录下来,特别是遇到的坑,会列在下面,一起参考学习。限于水平有限,若有错误,不吝赐教哈。那么,我们就开始正文吧。

1、注册账号

抖音开放平台地址:

https://open.douyin.com/platform

无独有偶,和其他第三方平台一样,进入开放平台注册账号后登录,平台会审核提交的信息,审核过了再创建应用(如果审核不过,是不让你创建应用的)。

2、创建应用

我们获取数据一般是用来做PC网站的,所以选择网站应用来创建,如实填写信息,等待审核。这里吐槽一下,和微信相比,抖音不管是小程序还是开放平台,审核的速度很慢,虽然在提交完信息后平台一般会提示三个工作日内审核,但是你可能还是要发邮件过去催。这里给大家看一下审核通过后的应用。

点击详情进入,看到如下内容,我们有了平台颁发的Client Key和Client Secret就可以开始撸代码了。

3、实现思路

也没什么特别的思路啦,就是引导用户扫描我们接入的二维码,用户在抖音APP端扫码确认或账号密码授权登录后,会重定向到我们的回调接口,并且附带授权临时票据(code),我们拿着code,以及ClientKey和ClientSecret等参数,通过API换取access_token,然后就可以通过access_token进行接口调用,获取用户基本信息及其他操作等。大致的流程就是这样子,接下来我们就来看一下实现的一些细节。

4、开发细节

4.1、选择资源中心 -> Open Api -> 账号授权及绑定 查看接口文档,

4.2、用户扫码授权,回调我们的接口,拿到code,再调用获取access_token的接口,也可以拿到用户对应的open_id,因为access_token是有时效性的,所以我们要做缓存,要在过期前先用refresh_token刷新延长access_token的有效期,又过期后只能让用户重新授权。

授权相关的service

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static final Logger logger = LoggerFactory.getLogger(OauthServiceImpl.class);
    private static final String OAUTH_STATE_SESSION_KEY = "OAUTH_STATE_SESSION_KEY";
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Value("${redis.key.douyinTokenKeyPrefix}")
    private String douyinTokenKeyPrefix;
    @Value("${redis.key.douyinRefreshTokenKeyPrefix}")
    private String douyinRefreshTokenKeyPrefix;
    @Value("${redis.key.douyinClientTokenKey}")
    private String douyinClientTokenKey;

     /**
     * 获取授权码(code)
     * @param clientKey
     * @param redirectUri
     * @param state
     * @return
     */
    @Override
    public String qrcodeAuth(String clientKey,String redirectUri,String state) {
        String requestUrl = Urls.BASE_URL+String.format(Urls.PERSON_CONNECT_URL,clientKey,redirectUri,state);    
        ShiroUtils.setSessionAttribute(OAUTH_STATE_SESSION_KEY,state);
        logger.info("qrConnect requestUrl=" + requestUrl);
        return requestUrl;
    }

    /**
     * 获取access_token
     * @param request
     * @param clientKey
     * @param clientSecret
     * @return
     */
    @Override
    public TokenResult accessToken(HttpServletRequest request,String clientKey,String clientSecret) {
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        Object sessionState = SecurityUtils.getSubject().getSession().getAttribute(OAUTH_STATE_SESSION_KEY);
        TokenResult token = new TokenResult();
        //校验state
        if (sessionState != null && state.equalsIgnoreCase(sessionState.toString())) {
            SecurityUtils.getSubject().getSession().removeAttribute(OAUTH_STATE_SESSION_KEY);
            String requestUrl = Urls.BASE_URL+String.format(Urls.ACCESS_TOKEN_URL,clientKey,clientSecret,code);
            JSONObject response = (CommonUtil.httpsRequestJson(requestUrl, "GET", null));
            JSONObject object = response.getJSONObject("data");
            logger.info("accessToken result=" + response);
            int errorCode = object.getInteger("error_code");
            String description = object.getString("description");
            if (errorCode == 0) {
                token.setErrorCode(0);
                token.setAccessToken(object.getString("access_token"));
                token.setExpiresIn(object.getInteger("expires_in"));
                token.setRefreshToken(object.getString("refresh_token"));
                token.setOpenId(object.getString("open_id"));
                token.setScope(object.getString("scope"));
            } else {
                token.setErrorCode(errorCode);
                token.setDescription(description);
            }
        } else {
            token.setErrorCode(500);
            token.setDescription("state校验失败");
        }
        return token;
    }

    /**
     * 刷新access_token
     * @param clientKey
     * @param refreshToken
     * @return
     */
    @Override
    public TokenResult refreshToken(String clientKey,String refreshToken) {
        String requestUrl = Urls.BASE_URL+String.format(Urls.REFRESH_TOKEN_URL,clientKey,refreshToken);
        JSONObject response = (CommonUtil.httpsRequestJson(requestUrl, "GET", null));
        JSONObject object = response.getJSONObject("data");
        logger.info("refreshToken result=" + response);
        int errorCode = object.getInteger("error_code");
        String description = object.getString("description");
        TokenResult token = new TokenResult();
        if (errorCode == 0) {
            token.setErrorCode(0);
            token.setAccessToken(object.getString("access_token"));
            token.setExpiresIn(object.getInteger("expires_in"));
            token.setRefreshToken(object.getString("refresh_token"));
            token.setOpenId(object.getString("open_id"));
            token.setScope(object.getString("scope"));
        } else {
            token.setErrorCode(errorCode);
            token.setDescription(description);
        }
        return token;
    }

授权相关的controller

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 @Value("${redis.key.douyinTokenKeyPrefix}")
    private String douyinTokenKeyPrefix;
    @Value("${redis.key.douyinRefreshTokenKeyPrefix}")
    private String douyinRefreshTokenKeyPrefix;
    @Value("${open.douyin.clientKey}")
    private String clientKey;
    @Value("${open.douyin.clientSecret}")
    private String clientSecret;

     /**
     * 抖音授权登录
     * @param anchorUuid
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "qrcodeAuth")
    public void qrcodeAuth(String anchorUuid, HttpServletResponse response) throws IOException {
        String redirectUrl = parameter.getSERVER_PATH() + "/mobile/douyin/authCallback";
        String state = UuidUtils.randomUUID() + "::" + anchorUuid;
        String requestUrl = oauthService.qrcodeAuth(clientKey, URLEncoder.encode(redirectUrl, "UTF-8"), state);
        response.sendRedirect(requestUrl);
    }
    
    /**
     * 抖音授权回调
     * @param request
     * @return
     */
    @RequestMapping(value = "authCallback")
    public void authCallback(HttpServletRequest request) {
        String state = request.getParameter("state");
        String anchorUuid = state.split("::")[1];
        TokenResult result = oauthService.accessToken(request, clientKey, clientSecret);
        if (result.getErrorCode() == 0) {
            String openId = result.getOpenId();
            String accessToken = result.getAccessToken();
            //保存accessToken等信息到缓存
            stringRedisTemplate.opsForValue().set(douyinTokenKeyPrefix + anchorUuid,
                    accessToken, 14, TimeUnit.DAYS);
            stringRedisTemplate.opsForValue().set(douyinRefreshTokenKeyPrefix + anchorUuid,
                    result.getRefreshToken(), 29, TimeUnit.DAYS);
            logger.info("accessToken===" + accessToken);
            anchorService.saveDouyin(accessToken, anchorUuid, openId);
        }
    }

4.3、根据access_token和open_id就可以获取到该用户的基本信息和粉丝统计数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
     * 获取用户信息
     * @param accessToken
     * @param openId
     * @return
     */
    @Override
    public JSONObject userInfo(String accessToken,String openId) {
        String requestUrl = Urls.BASE_URL+String.format(Urls.USERINFO_URL,accessToken,openId);
        JSONObject response = (CommonUtil.httpsRequestJson(requestUrl, "GET", null));
        JSONObject object = response.getJSONObject("data");
        logger.info("userInfo result=" + response);
        return object;
    }

     /**
     * 获取用户粉丝数据
     * @param accessToken
     * @param openId
     * @return
     */
    @Override
    public JSONObject fansData(String accessToken,String openId) {
        String requestUrl = Urls.BASE_URL+String.format(Urls.FANS_DATA_URL,accessToken,openId);
        JSONObject response = (CommonUtil.httpsRequestJson(requestUrl, "GET", null));
        JSONObject object = response.getJSONObject("data");
        logger.info("fansData result=" + response);
        return object;
    }

用户信息接口没有返回该用户的粉丝数,倒是在粉丝统计数据接口那边返回来粉丝数,可以在这边拿到粉丝数存到用户表,结合前端开发,把数据传给前端就可以显示出来了。这边叫了一个漂亮的小姐姐授权了,下面有短视频截图,你们就说好不好看吧。

用户基本信息

粉丝年龄分布、区域分布和性别分布

粉丝活跃分布

粉丝设备分布

粉丝兴趣分布

4.4、根据access_token和open_id就可以获取到该用户所有的抖音短视频数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 /**
     * 该接口用于分页获取用户所有视频的数据。返回的数据是实时的。
     * 列出已发布的视频
     * @param accessToken
     * @param openId
     * @param cursor
     * @param count
     * @return
     */
    @Override
    public JSONObject videoList(String accessToken,String openId,Long cursor,Integer count) {
        String requestUrl = Urls.BASE_URL+String.format(Urls.VIDEO_LIST_URL,accessToken,openId,cursor,count);
        JSONObject response = (CommonUtil.httpsRequestJson(requestUrl, "GET", null));
        logger.info("videoList result=" + response);
        return response;
    }

和粉丝数一样,开放平台没有提供接口直接获取用户的作品数、点赞数、总评论数、总分享数、平均点赞数、平均评论数、平均分享数,所以我们在获取到所有视频的时候要根据每条视频返回来的相应字段计算出这些数据再存到数据库,结合前端开发,把数据传给前端就可以显示出来了。

这里不得不吐槽一下,像粉丝数、作品数、点赞数、总评论数、总分享数等这些和用户相关的字段应该统计出来在用户信息那个接口就要返回来的,这样能给开发者省了很多时间,而且更符合常理,不知道抖音是怎么想的。

5、总结

5.1、看完这些代码之后,其实也不难,和对接其他第三方接口一样,只要照着文档写,总能调出结果来。现在看到的抖音开放平台文档是更新过的,看上去会比之前要好些,不管是版面、注意点还是参数注释都有改进,虽然还是没提供demo下载,但是增加了几种语言的接口调用样例虽然没有什么实际的作用,但是手心手背都是肉,还是知足些吧。

5.2、第一次对接新的第三方接口基本都有坑,大部分时候我们都寄希望于踩过坑的前人能够填好这些坑,给后来的人一些参考,少走弯路,节省时间,提高效率。起初抖音官方在飞书建了开放平台技术讨论群,可以在里面问问题,但是没多久上线了工单平台,要开发者有问题就提工单,就关掉了飞书群。有过对接第三方开发经验的应该都有感触,提交工单的途径来问问题的效率有多慢。下面就列出一些在开发过程中遇到的坑,小伙伴们感受一波。

  • 问题:当时对接的时候,修改回调域名需要重新审核,不知道现在平台改过来没有。 解决:所以为了保险起见,还是一开始就填正确,这点微信开放平台修改回调域名不需要审核。
  • 问题:在做OAuth 2.0授权时,scope传入多个,像这样scope=aweme.share,hotsearch,enterprise.data,user_info,fans.list,following.list,fans.data,video.create,video.delete,video.data,video.list,video.comment,总是报“权限非法”,我去掉一个就可以,我试了多次后猜想应该是scope太长了,最后一个权限被抖音截掉了(比如video.comment被截断变成了video.com,而video.com确实不是完整的权限,所以就报权限非法的错误)。

解决:然后向平台反应了,果然这是他们的一个bug,现在已经修复了。

  • 问题:接口不稳定,有时候可以,有时候不可以。 解决:所有的接口路径,最后面都要加上“/”,比如/fans/data/,这个不知道为什么,是问了抖音工作人员给出的解决方案。
  • 问题:调用授权二维码的时候,如果因为自身业务需要在用户扫码确认授权后回调我们的接口那边携带自己的参数,要注意,不能在回调接口的路径上拼接参数,因为回调那边获取不到,比如回调接口路径是/mobile/douyin/authCallback,不能这样携带参数/mobile/douyin/authCallback?userId=36781631,这应该也是被抖音限制了吧,但是做微信扫码授权就可以这样传参。 解决:扫码的时候为了安全需要传入一个随机数state,可以在state后面拼接我们的业务参数,然后在回调那边获取到state后截取。

上一篇:代小程序实现业务开发,99%还原公众号后台对服务类目管理的功能

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Thinkphp集成抖音SDK的实现方法
下载地址:抖音SDK官方下载:https://open.douyin.com/platform/doc/OpenAPI-devtool-sdk_download
码农编程进阶笔记
2021/07/20
1.6K0
Thinkphp集成抖音SDK的实现方法
微信开放平台PC端扫码登录[通俗易懂]
    点击二维码图标后,登录界面切换为如下样式(二维码),微信扫描二维码并授权,即可成功登录;
全栈程序员站长
2022/08/11
6K0
微信开放平台PC端扫码登录[通俗易懂]
第三方微信授权登录APP接入_使用第三方应用打开是什么意思
在微信开放平台 https://open.weixin.qq.com/ 注册成为开发者,具体步骤略
全栈程序员站长
2022/09/20
1.5K0
第三方微信授权登录APP接入_使用第三方应用打开是什么意思
记录一次微信PC授权登录以及微信公众号授权登录开发过程
记录一次微信PC授权登录以及微信公众号授权登录开发过程
Java架构师必看
2021/06/17
1.4K0
一杯茶的时间,上手第三方登录类库 JustAuth
JustAuth,如你所见,它仅仅是一个第三方授权登录的工具类库,它可以让我们脱离繁琐的第三方登录SDK,让登录变得So easy! 本专栏将会由浅入深,详细介绍如何使用JustAuth实现第三方登录,以及如何使用JustAuth的高级特性。
一只图雀
2020/05/07
2.5K0
微信发送模板消息
由于微信自 2023 年 9 月 20 日起,下发统一消息接口将被收回,无法下发小程序模板消息与公众号模板消息。
默存
2023/11/05
1K0
微信发送模板消息
一个基于 C# 开源的第三方 OAuth2 授权登录整合库
在我们的开发工作中有可能会对接过各种各样的第三方平台的登录授权,来获取用户的相关账号信息(如:微信登录、支付宝登录、飞书登录、钉钉登录、GitHub登录等等)。今天大姚给大家推荐一个基于 C# 开源的第三方 OAuth2 授权登录整合库:Netnr.Login。
追逐时光者
2025/02/07
1390
一个基于 C# 开源的第三方 OAuth2 授权登录整合库
微信开放平台实现扫码登录(java)
在进行第三方授权登录之前,需要在微信开放平台注册开发者账号,拿到相应的AppId和AppSecret以及redirect_uri,即可进行授权接入流程
全栈程序员站长
2022/08/12
1.6K0
微信开放平台实现扫码登录(java)
微信开放平台—-微信扫码登录
大家好,又见面了,我是你们的朋友全栈君。 告知:所有操作是基于域名已备案,并且具有企业级微信公众号! 1.准备工作 1.1.注册微信开放平台帐号 https://open.weixin.q
全栈程序员站长
2022/06/30
8.6K0
微信开放平台—-微信扫码登录
微信公众平台开发(四)——微信网页授权:获取用户openid&用户基本信息
在开发中,如果web产品需要使用到微信的功能,比如微信授权登录、微信支付、微信投票等,我是开发的东东是一个web项目,然而如果需要接入微信的话,就需要使用道微信的微信网页开发相关的功能。 其中我们需要的东西就是拿到微信服务器的回调,比如用户扫码登录我们的web项目时,用户正确授权之后,微信服务器能回调到我们期望的url并且返回相应的参数信息。
不愿意做鱼的小鲸鱼
2023/03/25
15.7K0
微信公众平台开发(四)——微信网页授权:获取用户openid&用户基本信息
C#版字节跳动SDK - SKIT.FlurlHttpClient.ByteDance
在我们日常开发工作中对接第三方开放平台,找一款封装完善且全面的SDK能够大大的简化我们的开发难度和提高工作效率。今天给大家推荐一款C#开源、功能完善的字节跳动SDK:SKIT.FlurlHttpClient.ByteDance。
追逐时光者
2023/10/28
3200
C#版字节跳动SDK - SKIT.FlurlHttpClient.ByteDance
SoringCloud(四) - 微信获取用户信息
1、项目介绍 2、微信公众平台 和 微信开放文档 2.1 微信公众平台 2.1.1 网址链接 https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo
化羽羽
2022/11/12
9950
SoringCloud(四) - 微信获取用户信息
微信开放平台:微信扫码登录功能
官方文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
全栈程序员站长
2022/08/11
7.4K0
微信开放平台:微信扫码登录功能
授权使用微信登陆第三方_微信图标改成WeChat
第三方平台系列文章,今天终于又开始更新了,今天继续学习微信(wechat)授权第三方登录
全栈程序员站长
2022/11/01
2.4K0
微信公众号网页授权获取用户openid
最近一个项目是在微信公众号内二次开发,涉及到微信公众号支付,根据文档要求想要支付就必须要获取到用户的openid。
庞小明
2018/09/19
17.3K0
微信公众号网页授权获取用户openid
Android笔记:集成原生微信授权获取用户信息登录
其实两年前做过这个功能,项目最近需要加上获取微信用户信息的需求,索性我就写成一篇文章,当做笔记 我在项目中用到的是点击一个按钮发起微信授权请求的需求,首先判断是否安装微信,如果安装微信则进行用户授权,授权成功之后通过微信提供的接口获取openID等用户信息,然后做自己的业务:
程思扬
2022/01/11
9650
Spring Security项目第三方登陆(四)
OAuth协议 image.png OAuth协议中的授权模式 授权码模式(authorization code) 密码模式(resource owner password credentials) 客户端模式(client credentials) 简化模式(implicit) 授权码模式 image.png spring social基本原理 image.png image.png QQ登陆 返回User封装好到对象 public class QQUserInfo { /**
楠楠
2019/06/15
2.1K0
记一次微信网页授权后获取用户信息并重定向
微信公众号开发还是比较简单的,但是写完之后就忘记了。每次写还要重新查文档,所以这次吧开发过程记录起来,有些细节问题也记录下来,以后用到就方便了。
何白白
2019/06/28
4.3K0
微信OAuth授权获取用户OpenId-JAVA(个人经验)
源码在这里。https://zb.oschina.net/market/opus/1444646_161 维护服务器。一份5元。自愿购买
小帅丶
2018/02/09
7.9K0
微信OAuth授权获取用户OpenId-JAVA(个人经验)
微信公众号网页授权登录[通俗易懂]
微信公众号网页授权登录: 前段时间做了一个微信公众号的项目,就是微信公众号的菜单点击我的个人中心,就向用户授权登录 获取用户的信息,进行业务逻辑的操作,微信公众号官方文档,这是我写的文章,里面有很多微信的官方 文档,希望对大家有用:https://blog.csdn.net/qq_41971087/article/details/82466647 在微信公众号官方文档中,看到微信页面开发,
全栈程序员站长
2022/09/05
2.5K0
微信公众号网页授权登录[通俗易懂]
推荐阅读
相关推荐
Thinkphp集成抖音SDK的实现方法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验