前期準備
提前準備、說明:目前對接推特api開發門戶分為3個版本,分別是免費的,100美金一個月的基礎版以及5000美金一個月的企業版,免費的目前就兩個接口可以調用,所以想要對接和使用推特最基本的也需要付100美元一個月,他們的區別如下圖,進入鏈接https://developer.twitter.com/en/portal/products/free? ?如下圖:
https://developer.twitter.com/en/portal/products/free
而基本的就可以使用很多接口了,這里就不闡述了,可以自己去里面看。
那么推特我們如何對接呢?下面給大家講一下詳細的流程:
1:第一步需要我們創建應用,開發者應用,由于我是開通了基礎版(100美金),所以我可以創建兩個應用,里面有3個選項包括生產,測試等等,我們直接選擇生產就好了,免費的只能創建一個應用,應用鏈接https://developer.twitter.com/en/portal/dashboard
??
2:創建成功以后還需要我們進去配置程序的公鑰私鑰,身份驗證設置等等,做好對接前期工作。
上面配置完成以后我們就可以看到我們自己的客戶ID了
開始對接
我們對接的是API v2的接口,大家一定要注意看接口文檔,別看到1.1獲取企業版的的去調別調不通。
說明:推特對接分為V1.1 、V2 以及企業版的Gnip2.0,這里目前使用的是V2的形式來對接的,V1.1對接一直報權限不足不給用,具體什么原因有知道的小伙伴可以告訴我一下,建議大家對接的時候去看一下?文檔?。那么如何獲取用戶的code以及Token呢?下面直接上代碼。
https://twitter.com/i/oauth2/authorize?
client_id=c3dqYzExdmo4VmpNY2tjbnFPNDM6MTpjaQ
&scope=tweet.read%20offline.access%20tweet.write%20tweet.moderate.write%20users.read%20follows.read%20follows.write
&response_type=code
&redirect_uri=http://8kvjtw.natappfree.cc/test/getTuiteCode
&state=profile&code_challenge=0ioze5m20493ny2
&code_challenge_method=plain參數說明:
client_id = 上面圖里面的客戶IDscope = 你需要用戶給你授權的權限,每個權限都是以%20分割,下圖會詳細介紹具體怎么來的response_type=code 這個是固定的,表示我們要去用戶的coderedirect_uri = 回調地址,獲取到code以后會回調到哪里,這里建議回調到前端頁面,讓前端在地址里面取出code返給后端,類似于這樣的 http://8kvjtw.natappfree.cc/test/getTuiteCode?state=profile&code=VmtmRFlDaXdV....code的值state=自己隨機定義字符串,回調里面會給你帶回來的code_challenge=隨機定義一串字符,但是換取Token的時候需要傳一樣的過去哦,這里重點記一下code_challenge_method=plain 表示不加密隨機字符
?scope :字段解釋,可以去下圖里面找出支持用戶授權的權限標識就好
直接在瀏覽器里面打開會出現下面這樣的,點擊授權應用就會回調到我們上面設置的回調地址里面,并且里面會帶兩個參數,一個是code,另一個就是我們設置的state也會帶給我們,參數都是拼接在回調地址后面的。
根據code換取token
Maven依賴
<dependency><groupId>oauth.signpost</groupId><artifactId>signpost-core</artifactId><version>1.2.1.2</version> </dependency><dependency><groupId>oauth.signpost</groupId><artifactId>signpost-commonshttp4</artifactId><version>1.2.1.2</version> </dependency><dependency><groupId>com.twitter</groupId><artifactId>twitter-api-java-sdk</artifactId><version>1.1.4</version> </dependency><dependency><groupId>commons-httpclient</groupId><artifactId>commons-httpclient</artifactId><version>3.1</version> </dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>29.0-jre</version> </dependency>
推特相關配置、文檔:https://developer.twitter.com/en/docs/authentication/oauth-2-0/user-access-token
/*** 推特相關配置*/
public class TwitterConfig {/*** 客戶id和客戶私鑰*/public static final String CLIENT_ID = "c3dqYzExdmo4VmpNY2t1111MTpjaQ";public static final String CLIENT_SECRET = "kfuA39dCX6tEG1111deXZHpOV-fjv9umx55ZdccCkNONjea";/*** 應用KYE和私鑰*/public static final String CONSUMER_KEY = "lhyfiDV3nX1111ffGeHMR";public static final String CONSUMER_SECRET = "BRNxnV5LxN23MlW4BCOdiSpQkQ1rn11119jtptduIkcwjB";/*** 應用的TOKEN*/public static final String ACCESS_TOKEN = "1482941195941633-A8xyN5xuqCrRJwj111dbFgkbStu";public static final String ACCESS_TOKEN_SECRET = "oZaKBphpooOR7GMBB3EFELIkU1111vzoXPAQ";}
@Data
@Accessors(chain = true)
public class TwitterDto {/*** 獲取的訪問令牌*/private String accessToken;/*** 刷新令牌*/private String refreshToken;}
/*** 根據code獲取用戶token* @param code 根據code換取token* @param refreshToken 根據token刷新token* @return*/public TwitterDto requestBearerToken(String code,String refreshToken) {try {String clientId = URLEncoder.encode(TwitterConfig.CLIENT_ID, "UTF-8");String clientSecret = URLEncoder.encode(TwitterConfig.CLIENT_SECRET, "UTF-8");//商戶id和商戶的私鑰String credentials = clientId + ":" + clientSecret;//對商戶id和私鑰機密一下String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes());//這個地址一定要和獲取code鏈接里面填的回調地址保持一致(惡心)String redirectURI = "http://8kvjtw.natappfree.cc/test/getTuiteCode";//請求、換取Token的地址URL url = new URL("https://api.twitter.com/2/oauth2/token");HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("POST");connection.setRequestProperty("Authorization", "Basic " + base64Credentials);connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");connection.setDoOutput(true);connection.setDoInput(true);String data = "";if(StringUtils.isBlank(refreshToken)){//authorization_code、refresh_token、client_credentials//我們這里是根據code換取Token所以選擇authorization_codeString grantType = "authorization_code";//獲取令牌需要的參數 code_verifier 需要和獲取code傳入參數 code_challenge 保持一致data = "grant_type=" + grantType + "&code=" + code + "&redirect_uri=" + redirectURI+"&client_id="+TwitterConfig.CLIENT_ID+"&client_secret="+TwitterConfig.CLIENT_SECRET+"&code_verifier=0ioze5m20493ny2";}else{//下面是通過刷新令牌的Token去換取新的Token,房子Token過期//authorization_code、refresh_token、client_credentialsString grantType = "refresh_token";//刷新令牌需要的參數data = "refresh_token="+refreshToken+"&grant_type=" + grantType + "&client_id="+TwitterConfig.CLIENT_ID+"&client_secret="+TwitterConfig.CLIENT_SECRET+"&code_verifier=challenge";}connection.getOutputStream().write(data.getBytes("UTF-8"));BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));StringBuilder response = new StringBuilder();String line;while ((line = reader.readLine()) != null) {response.append(line);}reader.close();String jsonResponse = response.toString();JSONObject json = JSON.parseObject(jsonResponse);TwitterDto twitterDto = new TwitterDto();Object accessToken = json.get("access_token");//我們實際使用TokentwitterDto.setAccessToken(accessToken == null ? null : accessToken.toString());//當我們使用的Token過期以后可以用這個來換取新的TokenaccessToken = json.get("refresh_token");twitterDto.setRefreshToken(accessToken == null ? null : accessToken.toString());return twitterDto;} catch (Exception e) {e.printStackTrace();return null;}}
@Slf4j
@RestController
@RequestMapping("/test")
@Api(tags = "測試")
@Transactional(isolation = Isolation.READ_COMMITTED)
public class TestController extends BaseComponent {@Autowiredprivate TwitterService twitterService;@GetMapping("getTuiteCode")@ApiOperation("測試推特code")public Map<String, String> getTuiteCode(String code, String state) {Map<String, String> map = new HashMap<>();TwitterDto bearerToken = twitterService.requestBearerToken(code,null);//刷新一下令牌//bearerToken = twitterService.requestBearerToken(code,bearerToken.getRefreshToken());System.out.println("Bearer Token: " + bearerToken.getAccessToken());map.put("Token", bearerToken.getAccessToken());map.put("state", state);return map;}
}
這就是一個完整的換取Token的流程,后面章節介紹如何使用Token操作用戶相關數據