9

我目前正在开发 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

任何人都可以帮助我解决这个问题我想通过改造本身来实现这个。

4

1 回答 1

8

最后我找到了解决方案希望这对其他人有帮助

我浏览了各种文件

1)使用 WooCommerce REST API – 简介

2) woocommerce-rest-api-docs

3)抄写员

4)抄写员:1.3.5

在参考了上述文档和源代码后,我最终创建了一个库,为 woocommerce HTTP android 执行 OAuth 1.0a “单腿”身份验证

完整的描述已添加到我的图书馆的自述部分

在这里查看图书馆

WoocommerceAndroidOAuth1 库

于 2016-10-11T20:22:29.727 回答