2017-12-13 2 views
2

here과 같이 "토큰 검색 (코드 흐름)"을 사용하여 Reddit API에 대한 OAuth2를 통해 액세스 토큰을 검색합니다. 나는 "code"문자열을 얻을 수 있었지만 액세스 토큰을 검색하려고 시도 할 때 unsupported_grant_type 오류가 발생합니다. Retrofit2를 사용하여이 작업을 수행하고 싶습니다.Reddit API Unsupported_grant_type 추가 기능 (Java)

private void getAccessToken(String code) { 

    if (mRetrofit == null) { 
     mRetrofit = new Retrofit.Builder() 
       .baseUrl(RedditConstants.REDDIT_BASE_URL) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build(); 
    } 
    Api api = mRetrofit.create(Api.class); 

    String authString = RedditConstants.REDDIT_CLIENT_ID + ":"; 
    String encodedAuthString = Base64.encodeToString(authString.getBytes(), Base64.NO_WRAP); 

    Map<String, String> headers = new HashMap<>(); 
    // headers.put("Content-Type", "application/x-www-form-urlencoded"); 
    // headers.put("Accept", "application/json"); 
    headers.put("Authorization", "Basic " + encodedAuthString); 
    headers.put("grant_type" , "authorization_code"); 
    headers.put("code", code); 
    headers.put("redirect_uri", RedditConstants.REDDIT_REDIRECT_URL); 
    headers.put("User-Agent", RedditConstants.REDDIT_USER_AGENT); 

    Call<RedditAccessToken> call = api.login(headers, MediaType.parse("application/x-www-form-urlencoded")); 
    call.enqueue(new Callback<RedditAccessToken>() { 
     @Override 
     public void onResponse(Call<RedditAccessToken> call, Response<RedditAccessToken> response) { 
       Log.d("Findme", "body: " + response.body().toString()); 
       Log.d("Findme", "response: " + response.toString()); 
     } 

     @Override 
     public void onFailure(Call<RedditAccessToken> call, Throwable t) { 
      Log.e("Fineme", "onFailure: " + t.getMessage()); 
     } 
    }); 

} 

로그 결과 :

D/Findme: body: RedditAccessToken{scope='null', token_type='null', 
error='unsupported_grant_type', expires_in='0', access_token='null', 
refresh_token='null'} 
D/Findme: response: Response{protocol=h2, code=200, message=, 
url=https://www.reddit.com/api/v1/access_token/} 

개조 인터페이스 :

public interface Api { 

    @POST("access_token/") 
    Call<RedditAccessToken> login (
     @HeaderMap Map<String, String> headers, 
     @Header("Content-Type") MediaType contentType 
    ); 
} 

개조 데이터 모델 :

public class RedditAccessToken { 

    @SerializedName("scope") 
    @Expose 
    private String scope; 

    @SerializedName("token_type") 
    @Expose 
    private String token_type; 

    @SerializedName("expires_in") 
    @Expose 
    private long expires_in; 

    @SerializedName("access_token") 
    @Expose 
    private String access_token; 

    @SerializedName("refresh_token") 
    @Expose 
    private String refresh_token; 

    @SerializedName("error") 
    @Expose 
    private String error; 

    public String getScope() { 
     return scope; 
    } 

    public String getRefresh_token() { 
     return refresh_token; 
    } 

    public void setRefresh_token(String refresh_token) { 
     this.refresh_token = refresh_token; 
    } 

    public void setScope(String scope) { 
     this.scope = scope; 
    } 

    public String getToken_type() { 
     return token_type; 
    } 

    public void setToken_type(String token_type) { 
     this.token_type = token_type; 
    } 

    public long getExpires_in() { 
     return expires_in; 
    } 

    public void setExpires_in(long expires_in) { 
     this.expires_in = expires_in; 
    } 

    public String getAccess_token() { 
     return access_token; 
    } 

    public void setAccess_token(String access_token) { 
     this.access_token = access_token; 
    } 

    @Override 
    public String toString() { 
     return "RedditAccessToken{" + 
       "scope='" + scope + '\'' + 
       ", token_type='" + token_type + '\'' + 
       ", error='" + error + '\'' + 
       ", expires_in='" + expires_in + '\'' + 
       ", access_token='" + access_token + '\'' + 
       ", refresh_token='" + refresh_token + '\'' + 
       '}'; 
    } 

    public String getError() { 
     return error; 
    } 

    public void setError(String error) { 
     this.error = error; 
    } 
} 

답변

0

나는 오류를 해결 한 모든 것이 지금 잘 작동 . 먼저 MIME 형식을 application/x-www-form-urlencoded로 자동 조정하는 Retrofit Annotation @FormUrlEncoded를 사용해야합니다. 또한 HTTP Basic Auth String 헤더 만 필요합니다. 다른 POST 데이터는 Retrofit Fields로 제출해야합니다. 이러한 변경으로 인해 다음과 같은 코드가 생성되었습니다.

String authString = RedditConstants.REDDIT_CLIENT_ID + ":"; 
String encodedAuthString = 
     Base64.encodeToString(authString.getBytes(), Base64.NO_WRAP); 

Map<String, String> headers = new HashMap<>(); 
headers.put("Authorization", "Basic " + encodedAuthString); 

Map<String, String> fields = new HashMap<>(); 
fields.put("grant_type", "authorization_code"); 
fields.put("code", code); 
fields.put("redirect_uri", RedditConstants.REDDIT_REDIRECT_URL); 
fields.put("User-Agent", RedditConstants.REDDIT_USER_AGENT); 


Call<RedditAccessToken> call = api.login(headers, fields); 
call.enqueue(new Callback<RedditAccessToken>() 

개조 인터페이스 :

public interface Api { 

    @FormUrlEncoded 
    @POST("access_token/") 
    Call<RedditAccessToken> login (
      @HeaderMap Map<String, String> headers, 
      @FieldMap Map<String, String> fields 
    ); 
}