简体   繁体   中英

Retrofit + Instagram API returns error 400 when requesting for access token

New to retrofit and am trying to consume Instagram API using retrofit. Below is the setup. First I define the Interface for communicating with the Instagram API

public interface API {
    @POST("oauth/access_token")
    Call<AccessToken> getAccessToken(@Body TokenRequest tokenRequest);
}

Below is my Implementation

public class APIPresenter implements Callback<List<APIResponse>> {

static final String BASE_URL = "https://api.instagram.com/";

public void startI(String code){
    Gson gson = new GsonBuilder()
            .setLenient()
            .create();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();

    API r = retrofit.create(API.class);

    Call<AccessToken> call = r.getAccessToken(new TokenRequest("CLIENT_ID", "CLIENT_SECRET", "authorization_code", "redirecturi", code));
    call.enqueue(new Callback<AccessToken>() {
        @Override
        public void onResponse(Call<AccessToken> call, Response<AccessToken> response) {
           // Log.i("WORKING", response.body().access_token + " " + response.body().user.getUsername());
            Log.i("WORKING", String.valueOf(response.code()));
        }

        @Override
        public void onFailure(Call<AccessToken> call, Throwable t) {
            t.printStackTrace();
        }
    });
}

TokenRequest

public class TokenRequest {
    private String client_id;
    private String client_secret;
    private String grant_type;
    private String  redirect_uri;
    private String code;

    public TokenRequest(String client_id, String client_secret, String grant_type, String redirect_uri, String code) {
        this.client_id = client_id;
        this.client_secret = client_secret;
        this.grant_type = grant_type;
        this.redirect_uri = redirect_uri;
        this.code = code;
    }
}

AccessToken model

public class AccessToken {

    @SerializedName("access_token")
    @Expose
    public String access_token;
    @SerializedName("user")
    @Expose
    public User user;

}

Problem is that when I try to output the contents of the response in the onResponse method, I get a null. I'm not sure what I'm doing wrong

Update I'm getting the following error message

{"code": 400, "error_type": "OAuthException", "error_message": "You must provide a client_id"}

I managed to solve this issue, issue was Instagram doesn't support sending the parameters as URL parameters, they must be sent in the body content of the POST. The content type should be set to "application/x-www-form-urlencoded".

This is how you you accomplish it with the code above

You have to add @FormURLEncoded annotation before the POST method, this will only work @Field annotation, hence the @Body content shall be replaced with the following @Field annotation.

public interface API {
@FormURLEncoded
@POST("oauth/access_token")
Call<AccessToken> getAccessToken(
        @Field("client_id") String client_id,
        @Field("client_secret") String client_secret,
        @Field("grant_type") String grant_type,
        @Field("redirect_uri") String redirect_uri,
        @Field("code") String code);
}

This is how you will send the details to your getAccessToken method on the Interface

 Call<AccessToken> call = r.getAccessToken("CLIENT_ID", "CLIENT_SECRET", "authorization_code", "redirecturi", code);

This should work perfectly!

You are posting client_id and other fields in the wrong way. Look how it is implemented in similar project:

public static String requestOAuthUrl(final String clientId, final String redirectUri, final Scope... scopes) throws URISyntaxException {
        final StringBuilder urlBuilder = new StringBuilder();
        urlBuilder.append("response_type=").append("token");
        urlBuilder.append("&client_id=").append(clientId);
        urlBuilder.append("&redirect_uri=").append(redirectUri);
        if (scopes != null) {
            final StringBuilder scopeBuilder = new StringBuilder();
            for (int i = 0; i < scopes.length; i++) {
                scopeBuilder.append(scopes[i]);
                if (i < scopes.length - 1) {
                    scopeBuilder.append(' ');
                }
            }
            urlBuilder.append("&scope=").append(scopeBuilder.toString());
        }
        return new URI("https", "instagram.com", "/oauth/authorize", urlBuilder.toString(), null).toString();
    }

It is taken from https://github.com/wearemakery/retrogram

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM