我目前正在开发 woocommerce api,我需要使用改造来集成 api。该网站采用HTTP,因此 HTTP 基本身份验证不能通过普通 HTTP 使用,因为密钥容易被拦截。API 使用 OAuth 1.0a “单腿”身份验证来确保您的 API 密钥不会被截获。我已经阅读了这篇文章以了解在 http 上使用哪种 OAuth 方法。
我已经使用Scribe成功实现了 api,但我想使用改造来实现 api,在谷歌搜索后我发现 Interceptor 是 Jake Wharton Oauth1SigningInterceptor。
所以我在改造身份验证时实现了这一点,但 api 调用返回
{"code":"woocommerce_rest_cannot_view","message":"Sorry, you cannot list resources.","data":{"status":401}}
如果我使用Scribe调用相同的 api返回成功的响应
下面是我如何调用 Api
BasicAuthInterceptor.java(修改自杰克沃顿 Oauth1SigningInterceptor)
public class BasicAuthInterceptor implements Interceptor {
private static final Escaper ESCAPER = UrlEscapers.urlFormParameterEscaper();
private static final String OAUTH_CONSUMER_KEY = "oauth_consumer_key";
private static final String OAUTH_NONCE = "oauth_nonce";
private static final String OAUTH_SIGNATURE = "oauth_signature";
private static final String OAUTH_SIGNATURE_METHOD = "oauth_signature_method";
private static final String OAUTH_SIGNATURE_METHOD_VALUE = "HMAC-SHA1";
private static final String OAUTH_TIMESTAMP = "oauth_timestamp";
private static final String OAUTH_VERSION = "oauth_version";
private static final String OAUTH_VERSION_VALUE = "1.0";
private final String consumerKey;
private final String consumerSecret;
private final Random random;
private BasicAuthInterceptor(String consumerKey, String consumerSecret, Random random) {
this.consumerKey = consumerKey;
this.consumerSecret = consumerSecret;
this.random = random;
}
@Override
public Response intercept(Chain chain) throws IOException {
return chain.proceed(signRequest(chain.request()));
}
public Request signRequest(Request request) throws IOException {
byte[] nonce = new byte[32];
random.nextBytes(nonce);
String oauthNonce = ByteString.of(nonce).base64().replaceAll("\\W", "");
String oauthTimestamp = String.valueOf(System.currentTimeMillis());
String consumerKeyValue = ESCAPER.escape(consumerKey);
SortedMap<String, String> parameters = new TreeMap<>();
parameters.put(OAUTH_CONSUMER_KEY, consumerKeyValue);
parameters.put(OAUTH_NONCE, oauthNonce);
parameters.put(OAUTH_TIMESTAMP, oauthTimestamp);
parameters.put(OAUTH_SIGNATURE_METHOD, OAUTH_SIGNATURE_METHOD_VALUE);
parameters.put(OAUTH_VERSION, OAUTH_VERSION_VALUE);
HttpUrl url = request.url();
for (int i = 0; i < url.querySize(); i++) {
parameters.put(ESCAPER.escape(url.queryParameterName(i)),
ESCAPER.escape(url.queryParameterValue(i)));
}
RequestBody requestBody = request.body();
Buffer body = new Buffer();
if (requestBody != null) {
requestBody.writeTo(body);
}
while (!body.exhausted()) {
long keyEnd = body.indexOf((byte) '=');
if (keyEnd == -1) throw new IllegalStateException("Key with no value: " + body.readUtf8());
String key = body.readUtf8(keyEnd);
body.skip(1); // Equals.
long valueEnd = body.indexOf((byte) '&');
String value = valueEnd == -1 ? body.readUtf8() : body.readUtf8(valueEnd);
if (valueEnd != -1) body.skip(1); // Ampersand.
parameters.put(key, value);
}
Buffer base = new Buffer();
String method = request.method();
base.writeUtf8(method);
base.writeByte('&');
base.writeUtf8(ESCAPER.escape(request.url().newBuilder().query(null).build().toString()));
base.writeByte('&');
boolean first = true;
for (Map.Entry<String, String> entry : parameters.entrySet()) {
if (!first) base.writeUtf8(ESCAPER.escape("&"));
first = false;
base.writeUtf8(ESCAPER.escape(entry.getKey()));
base.writeUtf8(ESCAPER.escape("="));
base.writeUtf8(ESCAPER.escape(entry.getValue()));
}
String signingKey =
ESCAPER.escape(consumerSecret);// + "&" + ESCAPER.escape(accessSecret);
SecretKeySpec keySpec = new SecretKeySpec(signingKey.getBytes(), "HmacSHA1");
Mac mac;
try {
mac = Mac.getInstance("HmacSHA1");
mac.init(keySpec);
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new IllegalStateException(e);
}
byte[] result = mac.doFinal(base.readByteArray());
String signature = ByteString.of(result).base64();
String authorization = "OAuth "
+ OAUTH_CONSUMER_KEY + "=\"" + consumerKeyValue + "\", "
+ OAUTH_NONCE + "=\"" + oauthNonce + "\", "
+ OAUTH_SIGNATURE + "=\"" + ESCAPER.escape(signature) + "\", "
+ OAUTH_SIGNATURE_METHOD + "=\"" + OAUTH_SIGNATURE_METHOD_VALUE + "\", "
+ OAUTH_TIMESTAMP + "=\"" + oauthTimestamp + "\", "
+ OAUTH_VERSION + "=\"" + OAUTH_VERSION_VALUE + "\"";
Log.d("message","--"+authorization);
return request.newBuilder()
.addHeader("Authorization", authorization)
.addHeader("Content-Type", "application/json;charset=UTF-8")
.addHeader("Accept", "application/json;versions=1")
.build();
}
public static final class Builder {
private String consumerKey;
private String consumerSecret;
private Random random = new SecureRandom();
public Builder consumerKey(String consumerKey) {
if (consumerKey == null) throw new NullPointerException("consumerKey = null");
this.consumerKey = consumerKey;
return this;
}
public Builder consumerSecret(String consumerSecret) {
if (consumerSecret == null) throw new NullPointerException("consumerSecret = null");
this.consumerSecret = consumerSecret;
return this;
}
public Builder random(Random random) {
if (random == null) throw new NullPointerException("random == null");
this.random = random;
return this;
}
public BasicAuthInterceptor build() {
if (consumerKey == null) throw new IllegalStateException("consumerKey not set");
if (consumerSecret == null) throw new IllegalStateException("consumerSecret not set");
}
}
}
远程 API 调用
public final class RemoteApiCalls {
private static final String TAG = "RemoteApiCalls";
public static final class Builder {
RemoteRetrofitInterfaces mService;
Retrofit mRetrofit;
public Builder remoteApiCall(String url,Context mContext) {
return remoteApiCall(mContext,url, 40, 40, 40);
}
BasicAuthInterceptor oauth1 = new BasicAuthInterceptor.Builder()
.consumerKey("keyhere")//i have added keys
.consumerSecret("secert here")//i have added secertkeys
.build();
public Builder remoteApiCall(Context mContext, String url, int connectionTimeout, int readTimeout, int writeTimeout) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS).addInterceptor(interceptor).addInterceptor(oauth1)
.build();
mRetrofit = new Retrofit.Builder()
.baseUrl(url).addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
mService = mRetrofit.create(RemoteRetrofitInterfaces.class);
return this;
}
public void getProductCatogry()
{
Call<ProductCategoryResponse> mApiCall = mService.getListCategory();
mApiCall.enqueue(new Callback<ProductCategoryResponse>() {
@Override
public void onResponse(Call<ProductCategoryResponse> call, Response<ProductCategoryResponse> response) {
if (response.isSuccessful()) {
} else {
}
}
@Override
public void onFailure(Call<ProductCategoryResponse> call, Throwable t) {
t.printStackTrace();
}
});
}
}
}
RemoteRetrofitInterfaces.java
public interface RemoteRetrofitInterfaces {
@GET("products")
Call<ProductCategoryResponse> getListCategory();
}
在我打电话的主要活动中
new RemoteApiCalls.Builder().remoteApiCall("http://mywebsite.com/wp-json/wc/v1/",getApplicationContext()).getProductCatogry();
仍然收到 401 错误
{"code":"woocommerce_rest_cannot_view","message":"Sorry, you cannot list resources.","data":{"status":401}}
Woo Commerce 使用的版本是 2.6.4 版本 APi 版本是 v1
任何人都可以帮助我解决这个问题我想通过改造本身来实现这个。