Ошибка аутентификации WooCommerce Api с использованием java

У меня возникла проблема при подключении к WooCommerce API (http://woothemes.github.io/woocommerce-rest-api-docs/#authentication). Я успешно могу сгенерировать подпись с помощью java-программы, а также проверить сгенерированную подпись, имеющую ту же отметку времени и одноразовый номер, связанный с консолью (как указано в документе WooCommerce) для любого несоответствия, но сгенерированная подпись одинакова для связанного и вывода java приставка.

Процесс нашей работы описан ниже:

1. Мы сгенерировали подпись с помощью базовой строки подписи и секретного ключа, используя программу Java. Базовая строка подписи выглядит так:

GET&http%3A%2F%2FEndPointURL%2Fwc-api%2Fv2%2Forders&oauth_consumer_key%3D%26oauth_nonce%3D70810941%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1433226349%26oauth_version%3D1.0

2. Пока мы пытаемся получить доступ к URL-адресу http://EndPointURL/wc-api/v2/orders, отображается ошибка, указанная ниже:

{"errors":[{"code":"woocommerce_api_authentication_error","message":"Invalid Signature - provided signature does not match"}]}

3. Мы также сгенерировали подпись с помощью Linked in test Console, используя то же значение метки времени и одноразового номера, и получили ту же подпись. Но мы не можем получить доступ к данным.

Код Java, который я использую, приведен ниже:

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;


public class OAuthForWooCommerce {

private static String key = "consumer_Key";
private static String secret = "consumer_Secret";

private static final String HMAC_SHA1 = "HmacSHA1";

private static final String ENC = "UTF-8";

private static Base64 base64 = new Base64();


private static String getSignature(String url, String params)
        throws UnsupportedEncodingException, NoSuchAlgorithmException,
        InvalidKeyException {
    /**
     * base has three parts, they are connected by "&": 1) protocol 2) URL
     * (need to be URLEncoded) 3) Parameter List (need to be URLEncoded).
     */
    StringBuilder base = new StringBuilder();
    base.append("GET&");
    base.append(url);
    base.append("&");
    base.append(params);
    System.out.println("String for oauth_signature generation:" + base);
    // yea, don't ask me why, it is needed to append a "&" to the end of
    // secret key.
    byte[] keyBytes = (secret + "&").getBytes(ENC);

    SecretKey key = new SecretKeySpec(keyBytes, HMAC_SHA1);

    Mac mac = Mac.getInstance(HMAC_SHA1);
    mac.init(key);

    // encode it, base64 it, change it to string and return.
    return new String(base64.encode(mac.doFinal(base.toString().getBytes(
            ENC))), ENC).trim();
}


public static void main(String[] args) throws ClientProtocolException,
        IOException, URISyntaxException, InvalidKeyException,
        NoSuchAlgorithmException {
     System.out.println("*** Welcome to WooCommerce Klipfolio integration Wizard ***");
    HttpClient httpclient = new DefaultHttpClient();
    List<NameValuePair> qparams = new ArrayList<NameValuePair>();
    // These params should ordered in key
    //qparams.add(new BasicNameValuePair("oauth_callback", "oob"));
    qparams.add(new BasicNameValuePair("oauth_consumer_key", key));
    String nonce = RandomStringUtils.randomAlphanumeric(32);
    //String nonce2 = URLEncoder.encode(nonce1, "UTF-8");
    qparams.add(new BasicNameValuePair("oauth_nonce", nonce));
    //qparams.add(new BasicNameValuePair("oauth_nonce", ""+ (int) (Math.random() * 100000000)));
    qparams.add(new BasicNameValuePair("oauth_signature_method",
            "HMAC-SHA1"));
    qparams.add(new BasicNameValuePair("oauth_timestamp", ""
            + (System.currentTimeMillis() / 1000)));
    qparams.add(new BasicNameValuePair("oauth_version", "1.0"));

    // generate the oauth_signature
    String signature = getSignature(URLEncoder.encode(
            "http://MY_END_URL/wc-api/v2/orders", ENC),
            URLEncoder.encode(URLEncodedUtils.format(qparams, ENC), ENC));
    System.out.println("Getting Oauth Signature...");
    // add it to params list
    qparams.add(new BasicNameValuePair("oauth_signature", signature));

    // generate URI which lead to access_token and token_secret.
    URI uri = URIUtils.createURI("http", "MY_END _URL", -1,
            "wc-api/v2/orders",
            URLEncodedUtils.format(qparams, ENC), null);

    System.out.println("Connecting to  the URL : \n"
            + uri.toString());

    HttpGet httpget = new HttpGet(uri);
    // output the response content.
    System.out.println("Getting Response from the server :");

    HttpResponse response = httpclient.execute(httpget);
    HttpEntity entity = response.getEntity();
    if (entity != null) {
        InputStream instream = entity.getContent();
        int len;
        byte[] tmp = new byte[2048];
        while ((len = instream.read(tmp)) != -1) {
            System.out.println(new String(tmp, 0, len, ENC));
        }
    }
}

}

Пожалуйста, дайте мне знать, где я делаю неправильно.

Спасибо,


person Archit    schedule 02.06.2015    source источник
comment
ты нашел ответ?   -  person Dilip Rajkumar    schedule 16.08.2015
comment
Нет, дело все еще находится на рассмотрении !!   -  person Archit    schedule 21.08.2015
comment
Я как бы решил проблему с помощью JS. Проблема заключается в вашей части кодирования, можете ли вы попробовать удалить +& при создании ключа   -  person Dilip Rajkumar    schedule 21.08.2015
comment
Вы видели этот код в Github?   -  person hram908    schedule 31.08.2015
comment
Пробовали ли вы wc-api (github.com/icoderman/wc-api-java ) ?   -  person Ibrahim.H    schedule 15.02.2019


Ответы (2)


Вы должны удалить номер версии из параметров, согласно документации. Я также думаю, что вам следует удалить «&», который вы добавили к секретному ключу при создании подписи, так как мне удалось получить 200 ответов без него.

Требуемые параметры: oauth_consumer_key, oauth_timestamp, oauth_nonce, oauth_signature и oauth_signature_method. oauth_version не требуется и должен быть опущен.

Вы также должны отсортировать параметры в порядке байтов, прежде чем добавлять их в строку, которую вы использовали для создания подписи.

Кроме того, я предлагаю вам выполнить отладку, изменив строка сообщения, чтобы увидеть подпись, которую вы отправили на сервер, и подпись, которую вы должны были отправить.

Например, вы можете изменить его на:

throw new Exception( __( 'Invalid Signature - provided signature does not match Secret:' . $user->woocommerce_api_consumer_secret . ', StringToSign: ' . $string_to_sign . ', TakenSign: ' . $consumer_signature . ', GeneratedSign: ' . $signature, 'woocommerce' ), 401 );
person Turgut Sarıçam    schedule 14.06.2015

Спасибо за ваш код Archit, он помог мне справиться с трудностями.

Я обновил ваш код, и ниже работает.

package com.woocommerce.experiments;

import org.apache.commons.codec.EncoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.net.URLCodec;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class OAuthForWooCommerce {

  private static String key = "ck_your_consumer_key";
  private static String secret = "cs_your_consumer_secret";

  private static final String HMAC_SHA1 = "HmacSHA1";

  private static final String ENC = "UTF-8";

  private static Base64 base64 = new Base64();

  private static String getSignature(String url, String params)
          throws UnsupportedEncodingException, NoSuchAlgorithmException,
          InvalidKeyException, EncoderException {
    /**
     * base has three parts, they are connected by "&": 1) protocol 2) URL
     * (need to be URLEncoded) 3) Parameter List (need to be URLEncoded).
     */
    StringBuilder base = new StringBuilder();
    base.append("GET&");

   //follow Step 2 and encode
    base.append(new URLCodec(Consts.UTF_8.displayName()).encode(url));
    base.append("&");
    base.append(params);

    System.out.println("String for oauth_signature generation: " + base);

    byte[] keyBytes = (String.format("%s", secret)).getBytes(ENC);

    SecretKey key = new SecretKeySpec(keyBytes, HMAC_SHA1);

    Mac mac = Mac.getInstance(HMAC_SHA1);
    mac.init(key);

    // encode it, base64 it, change it to string and return.
    String signature = new String(base64.encode(mac.doFinal(base.toString().getBytes(ENC))), ENC).trim();
    return signature;
  }


  public static void main(String[] args) throws IOException, URISyntaxException, InvalidKeyException,
          NoSuchAlgorithmException, EncoderException {

    String nonce = RandomStringUtils.randomAlphanumeric(32);

    Map<String, String> paramMap = new TreeMap<>();
    paramMap.put("oauth_consumer_key", key);
    paramMap.put("oauth_timestamp", "" + (System.currentTimeMillis() / 1000));
    paramMap.put("oauth_nonce", nonce);
    paramMap.put("oauth_signature_method", "HMAC-SHA1");

    List<NameValuePair> qparams = new ArrayList<>();

    //uksort( $params, 'strcmp' ) mimic
    paramMap.entrySet().stream().forEach(stringStringEntry -> qparams.add(new BasicNameValuePair(stringStringEntry.getKey(), stringStringEntry.getValue())));

    //double encode Step 3 (in order to replace '%' with '%25') after sorting (Step 4)
    String encodedParams = URLEncoder.encode(URLEncodedUtils.format(qparams, ENC), ENC);

    System.out.println("Encoded Params "+ encodedParams);

    String signature = getSignature("http://your_end_url/wc-api/v2/orders", encodedParams);

    qparams.add(new BasicNameValuePair("oauth_signature", signature));

    HttpClient httpclient = HttpClientBuilder.create().build();

    System.out.println("Getting Oauth Signature...");

    // generate URI which lead to access_token and token_secret.
    URI uri = URIUtils.createURI("http", "your_end_url", -1, "wc-api/v2/orders", URLEncodedUtils.format(qparams, ENC), null);

    System.out.println("Connecting to  the URL : \n" + uri.toString());

    HttpGet httpget = new HttpGet(uri);
    httpget.setHeader("X-Stream" , "true");

    // output the response content.
    System.out.println("Getting Response from the server :");

    HttpResponse response = httpclient.execute(httpget);
    HttpEntity entity = response.getEntity();

    System.out.println("Response Code " + response.getStatusLine().getStatusCode());

    if (entity != null) {
      System.out.println("Json response" + IOUtils.toString(entity.getContent(), ENC));
    }
  }
}

Я надеюсь, что это поможет вам (надеюсь, не поздно!) И другим. Пошаговый процесс аутентификации можно найти в Документация WooCommerce REST API< /а>

person OliverTester    schedule 24.03.2016