我正在使用twitter rest api,这是(
https://api.twitter.com/1.1/).
首先,我使用路标库生成oauth_signature.它运作良好.
上传状态端点(https://api.twitter.com/1.1/statuses/upload.json)运行良好,但如果状态参数包含“@”符号,则表示无效.所以这是我的代码
TwitterStatusesService.java
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface TwitterStatusesService {
@POST("/1.1/statuses/update.json")
Call<ResponseBody> update(@Query("status") String status,@Query("in_reply_to_status_id") String inReplyToStatusId,@Query("lat") Double lat,@Query("long") Double lon,@Query("media_ids") String mediaIds);
}
TwitterStatusesapiclient.java
import android.util.Log;
import com.twitter.sdk.android.core.TwitterauthToken;
import com.twitter.sdk.android.core.TwitterCore;
import com.twitter.sdk.android.core.TwitterSession;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Retrofit;
import se.akerfeldt.okhttp.signpost.OkHttpOAuthConsumer;
import se.akerfeldt.okhttp.signpost.SigningInterceptor;
public class TwitterStatusesClient {
private final String TAG = getClass().getSimpleName();
private static final String BASE_URL = "https://api.twitter.com/";
private final TwitterStatusesService apiService;
private static TwitterStatusesClient webServiceClient;
public static TwitterStatusesClient getInstance() {
if (webServiceClient == null)
webServiceClient = new TwitterStatusesClient();
return webServiceClient;
}
private TwitterStatusesClient() {
private TwitterStatusesClient() {
OkHttpOAuthConsumer consumer = new OkHttpOAuthConsumer(TWITTER_KEY,TWITTER_SECRET);
TwitterSession activeSession = TwitterCore.getInstance().getSessionManager().getActiveSession();
if (activeSession != null) {
TwitterauthToken authToken = activeSession.getAuthToken();
String token = authToken.token;
String secret = authToken.secret;
consumer.setTokenWithSecret(token,secret);
}
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new SigningInterceptor(consumer))
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.build();
apiService = retrofit.create(TwitterStatusesService.class);
}
public Call<ResponseBody> update(String status,String statusId,Double lat,Double lon,String mediaIds) {
return apiService.update(status,statusId,lat,lon,mediaIds);
}
}
调用api客户端
String status = "@example";
TwitterStatusesClient.getInstance().update(status,null,null).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call,Response<ResponseBody> response) {
Log.v(TAG,"onResponse");
progressDialog.dismiss();
try {
if (response.errorBody() != null) {
String error = response.errorBody().string();
Log.e(TAG,"Error : " + error);
ToastUtils.showErrorMessage(getContext(),"Error : " + error);
return;
}
String body = response.body().string();
Log.v(TAG,"body : " + body);
} catch (Exception e) {
e.printstacktrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call,Throwable t) {
Log.v(TAG,"onFailure");
t.printstacktrace();
}
});
给出错误:
{"errors":[{"code":32,"message":"Could not authenticate you."}]}
但是,如果我将使用状态变量“只是示例”而不是“@example”(具体点是删除@字符)正在工作.只有’@’符号不起作用.
编辑
这是我通过改装拦截器手动创建OAuth v1.0a签名签名代码:
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
String method = request.method();
String baseUrl = "https://api.twitter.com" + request.url().url().getPath();
String oauthToken = "";
String oauthTokenSecret = "";
TwitterSession activeSession = TwitterCore.getInstance().getSessionManager().getActiveSession();
if (activeSession != null) {
TwitterauthToken authToken = activeSession.getAuthToken();
oauthToken = authToken.token;
oauthTokenSecret = authToken.secret;
}
String oauthNonce = "TXZScw4M8TG";
String oauthSignatureMethod = "HMAC-SHA1";
String oauthTimestamp = String.valueOf(System.currentTimeMillis() / 1000);
String oauthVersion = "1.0";
String parameterString = "";
parameterString = OAuthParams.addParam(request,parameterString,"count");
parameterString = OAuthParams.addParam(request,"id");
parameterString = OAuthParams.addParam(request,"in_reply_to_status_id");
// if any parameter added to parameterString,append '&' character.
if (parameterString.length() > 0) {
parameterString += "&";
}
parameterString += "oauth_consumer_key=" + TWITTER_KEY + "&"
+ "oauth_nonce=" + oauthNonce + "&"
+ "oauth_signature_method=" + oauthSignatureMethod + "&"
+ "oauth_timestamp=" + oauthTimestamp + "&"
+ "oauth_token=" + oauthToken + "&"
+ "oauth_version=" + oauthVersion;
// add status parameter to parameterString.
parameterString = OAuthParams.addParam(request,"status");
Log.d(TAG,"normalizedParameters : " + parameterString);
Log.d(TAG,"parameterStringPercent : " + OAuth.percentEncode(parameterString));
String signatureBaseString = "";
signatureBaseString += OAuth.percentEncode(method) + "&";
signatureBaseString += OAuth.percentEncode(baseUrl) + "&";
signatureBaseString += OAuth.percentEncode(parameterString);
String oauthSignature = OauthSignature.generateSignature(signatureBaseString,TWITTER_SECRET,oauthTokenSecret);
String authorization = "OAuth oauth_consumer_key=\"" + TWITTER_KEY + "\"," +
"oauth_signature_method=\"HMAC-SHA1\"," +
"oauth_timestamp=\"" + oauthTimestamp + "\"," +
"oauth_nonce=\"" + oauthNonce + "\"," +
"oauth_version=\"1.0\"," +
"oauth_token=\"" + oauthToken + "\"," +
"oauth_signature=\"" + OAuth.percentEncode(oauthSignature) + "\"";
Log.w(TAG,"Authorization : " + authorization);
request = request.newBuilder()
.addHeader("Authorization",authorization)
.build();
return chain.proceed(request);
}
}).addInterceptor(interceptor).build();
OAuth.java
public static String percentEncode(String s) {
if (s == null) {
return "";
}
try {
return URLEncoder.encode(s,ENCODING)
// OAuth encodes some characters differently:
.replace("+","%20").replace("*","%2A")
.replace("%7E","~");
// This Could be done faster with more hand-crafted code.
} catch (UnsupportedEncodingException wow) {
throw new RuntimeException(wow.getMessage(),wow);
}
}
OAuthSignature.java
import android.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class OauthSignature {
public static String generateSignature(String signatueBaseStr,String oAuthConsumerSecret,String oAuthTokenSecret) {
byte[] byteHMAC = null;
try {
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec spec;
if (null == oAuthTokenSecret) {
String signingKey = OAuth.percentEncode(oAuthConsumerSecret) + '&';
spec = new SecretKeySpec(signingKey.getBytes(),"HmacSHA1");
} else {
String signingKey = OAuth.percentEncode(oAuthConsumerSecret) + '&' + OAuth.percentEncode(oAuthTokenSecret);
spec = new SecretKeySpec(signingKey.getBytes(),"HmacSHA1");
}
mac.init(spec);
byteHMAC = mac.doFinal(signatueBaseStr.getBytes());
} catch (Exception e) {
e.printstacktrace();
}
return new String(Base64.encode(byteHMAC,Base64.DEFAULT));
}
}
解决方法
我建议使用面料 –
https://fabric.io,它有各种各样的libs,如twitter登录,crashlytics和alss,你需要设置与Android工作室的面料插件.发布您可以发布/检索推文,无论您想发布什么.
对于您的问题 – 检查’@’是特殊符号,其中改造导致问题.这些问题是我在不同场景中遇到的改造.
尝试使用Fabric进行Twitter登录/ oAuth