开放文档
授权说明
快手开放平台是基于OAuth2协议
的开放授权和鉴权服务,接入前需要了解标准的OAuth2
的一些相关知识,可以参考文档 THE OAUTH 2.0 AUTHORIZATION FRAMEWORK
。开放平台提供了OAuth2
的两种授权方式,授权码code和客户端凭证client_credentials
,分别适用于需要用户授权的授权API调用场景,以及不需要用户授权的非授权API调用场景。
注:OAuth2
相关知识是接入必备,建议提前阅读。
授权方式
对于标识了“需用户授权”的API,需要使用OAuth2的code
授权方式,获取用户access_token
OAuth2的code授权流程及接口简介
当access_token
过期时,可以使用(在有效期内的)refresh_token
重新获取新的access_token
,不需要显式的用户授权过程,
若refresh_token
也过期了,则需要再次经过用户授权,因此需要关注refresh_token
的时效,需要在时效内用此接口再换取新的refresh_token
才不会出现用户授权频繁失效的情况。该接口只支持authorization_code
模式获取access_token
刷新,刷新得到新的access_token
和refresh_token
, 旧的refresh_token
随即在5分钟内失效。
- refresh_token 长时访问令牌,默认为180天
- access_token 临时访问令牌,作为调用授权API时的入参,过期时间为expires_in值 48小时
准备工作
创建应用
参考: 创建App指南
得到
APPKEY
APPSecret
授权 得到授权码,或者填写回调授权路由用于拿到授权grantCode
正文: 接入代码
授权码接入
@Configuration
@Slf4j
public class KsConfig {
@Value("${spring.profiles.active}")
private String activeProfile;
@Value("${app.key.ks}")
public String appKey ;
/**
* 获取 快手客户端
*
* @param ksProperties
* @return
*/
@Bean
public AccessTokenKsMerchantClient ksMerchantClient(KsProperties ksProperties) {
return new AccessTokenKsMerchantClient("https://openapi.kwaixiaodian.com",ksProperties.getAppKey(), ksProperties.getSignSecret());
}
}
@Resource // 钥匙
private KsProperties ksProperties;
@Resource
private RedisUtil redisUtil;
/**
* 获取授权令牌
* <p>
* 返回结果类型,1为正确,其他为不正确
* 临时访问令牌,作为调用授权API时的入参,过期时间为expires_in值,授权用户、app和权限组范围唯一决定一个access_token值
* 注: access_token过期时间,单位秒,默认为172800,即48小时
*
* @param ksShopConfig
* @return
*/
private Map<String, String> getKsAccessToken(KsShopConfig ksShopConfig) throws KsMerchantApiException {
Map<String, String> map = new HashMap<>();
getShopAccess(map, 店铺授权码, "Ks_refreshToken", "授权店铺名称", "Ks_accessToken");
return map;
}
/**
* 获取令牌
*
* @param map
* @throws KsMerchantApiException
*/
private void getShopAccess(Map<String, String> map, String code, String code_refreshToken, String shopName, String code_accessToken) throws KsMerchantApiException {
if (StringUtil.isNotBlank(code) && redisUtil.get(code_refreshToken) == null) {
KsAccessTokenResponse ksAccessTokenBuild = getKsAccessTokenBuild(code, shopName);
redisUtil.set(code_refreshToken, ksAccessTokenBuild.getRefreshToken(), ksAccessTokenBuild.getRefreshTokenExpiresIn());
redisUtil.set(code_accessToken, ksAccessTokenBuild.getAccessToken(), ksAccessTokenBuild.getExpiresIn());
} else if (redisUtil.get(code_refreshToken) != null) {
Object tokens = redisUtil.get(code_accessToken);
if (tokens != null) {
map.put(shopName, (String) tokens);
} else {
KsAccessTokenResponse ksAccessTokenResponse = refreshKsAccessToken((String) redisUtil.get(code_refreshToken), shopName);
redisUtil.set(code_refreshToken, ksAccessTokenResponse.getRefreshToken(), ksAccessTokenResponse.getRefreshTokenExpiresIn());
redisUtil.set(code_accessToken, ksAccessTokenResponse.getAccessToken(), ksAccessTokenResponse.getExpiresIn());
map.put(shopName, ksAccessTokenResponse.getAccessToken());
}
}
}
/**
* 构建快手 token获取
*
* @param shop
* @param grantCode
* @return
*/
private KsAccessTokenResponse getKsAccessTokenBuild(String grantCode, String shop) {
//不指定服务器地址,服务器地址默认为线上
OauthAccessTokenKsClient oauthAccessTokenKsClient = new OauthAccessTokenKsClient(ksProperties.getAppKey(), ksProperties.getAppSecret());
// 生成AccessToken
KsAccessTokenResponse response = null;
try {
response = oauthAccessTokenKsClient.getAccessToken(grantCode);
} catch (KsMerchantApiException e) {
e.printStackTrace();
}
if (response == null || response.getResult() != 1) {
log.info("获取授权失败名称: {} code:{} 错误返回参数 {}", shop, grantCode, response);
throw new AfterSaleException("获取授权失败名称: " + shop);
}
return response;
}
/**
* 刷新快手token
*/
private KsAccessTokenResponse refreshKsAccessToken(String refreshToken, String shop) throws KsMerchantApiException {
//不指定服务器地址,服务器地址默认为线上
OauthAccessTokenKsClient oauthAccessTokenKsClient
= new OauthAccessTokenKsClient(ksProperties.getAppKey(), ksProperties.getAppSecret());
KsAccessTokenResponse response = oauthAccessTokenKsClient.refreshAccessToken(refreshToken);
if (response == null || response.getResult() != 1) {
log.info("刷新店铺授权失败店铺名称: {} 错误返回参数 {}", shop, response);
throw new AfterSaleException("获取店铺授权失败店铺名称: " + shop);
}
return response;
}
client_credentials 凭证获取,适用于不需要商户授权的接口
String appKey = "your app key";
String appSecret = "your app secret";
OauthCredentialKsClient oauthCredentialKsClient = new OauthCredentialKsClient(appKey, appSecret);
// 生成AccessToken
try {
KsCredentialResponse response = oauthAccessTokenKsClient.getAccessToken(); System.out.println(JSON.toJSONString(response));
} catch (KsMerchantApiException e) {
e.printStackTrace();
}
拿到token
令牌调用需要的API