2017-12-13 14 views
2

hereのように「トークン検索(コードフロー)」を使用して、Reddit APIのOAuth2経由でアクセストークンを取得しています。私は "コード"文字列を取得することができましたが、アクセストークンを取得しようとするとunsupported_grant_typeエラーが発生します。私はこれを達成するためにRetrofit2を使用したいと思います。Reddit Api unsupported_grant_typeエラーRetrofit(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 
    ); 
}  
関連する問題