Получение списка товаров (Woocommerce Web API, C#)

Получение списка товаров (Woocommerce Web API, C#)

В этой статье я расскажу, как можно получить список товаров на С# используя Woocommerce Rest Api (ссылка на документацию).  Основной внимание будет уделено именно аутентификации, шифрованию и построению запроса с использование ключей cs_* и ck_*, получение которых мы рассмотрели в предыдущей статье.

WooCommerce ( далее WC) полностью интегрирован с API-интерфейсом WordPress REST. Это позволяет создавать, считывать, обновлять и удалять данные WC, используя запросы в формате JSON, также используя методы проверки API REST API.

Обратите внимание, что вам не требуется устанавливать плагин WP REST API.

Сперва настроим постоянные ссылки

Предварительно необходимо настроить постоянные ссылки WordPress (далее WP), для чего в WP выбираем пункт «Настройки» и подпункт «Постоянные ссылки» и в Общих настройках делаем активным пункт «Название записи»:

Создаем модель Product

Функционал API для работы с товарами, позволяет: создавать, просматривать, обновлять и удалять товары, а также делать это всё одновременно. Пройдя по ссылки на документацию Woocommerc Rest Api, вы можете найти все атрибуты товара(их несколько десятков), здесь я не буду вдаваться в подробное описание свойств товара. Поэтому объявим класс Product с тремя атрибутами:

public class Product
    {
        public int? id { get; set; }
        public string name { get; set; }   
        public string slug { get; set; }
    }

HTTP Метод для отправки запроса — GET.

Конечной точкой URL адреса для получения товаров будет http://www.ИмяВашегоСайта.ru/wp-json/wc/v2/products, для получения заказов соответвенно: http://www.ИмяВашегоСайта.ru/wp-json/wc/v2/orders  и т.д.

string wc_url = "http://transittea.ru/wp-json/wc/v2/products";      // Конечная точка URL
string wc_key = "ck_c143835aa0b15e06002fbefe9a4b48079ce4d777";      // Ключ 
string wc_secret = "cs_9ab0222dee1cfb6cf9bed16ef675f2b22412777&";   // Секретный ключ

Обратите внимание на добавленный, в соответствии с документацией, знак амперсанд (&) в конец строки с секретным ключем.

Список параметров передаваемых методом GET

Dictionary<string, string> dic = new Dictionary<string, string>();
dic.Add("oauth_consumer_key", wc_key);
dic.Add("oauth_nonce", Guid.NewGuid().ToString("N"));
dic.Add("oauth_signature_method", "HMAC-SHA256");
dic.Add("oauth_timestamp", Common.GetUnixTime(false));

При обращении к WC Rest Api необходимо передать следующие параметры:

  • oauth_consumer_key — это первый из сгенерированных в WP нами клачей;
  • oauth_nonce — случайно сгенерированная 32-символьная(рекомендуется) строка, уникальная для ключа пользователя;
  • oauth_signature_method — метод создания подписи(алгоритм хеширования HMAC-SHA1 или HMAC-SHA256), используя базовую строку подписи и секретный ключ с символом «&«;
  • oauth_timestamp — это Unix-время. REST API будет отклонять любые запросы, превышающие 15 минутное расхождение.

Для справки. Unix-время система описания моментов времени, принятая в Unix, представляет собой количество секунд, прошедших с полуночи, т.е. с 00:00:00 UTC 1 января 1970 года(четверга), время с этого момента называют «эрой Unix».

Теперь сама функция получения значения для параметра oauth_timestamp:

public static string GetUnixTime(bool micro)
{
            long unixtime = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).Ticks;

            if (!micro)
            {
                return unixtime.ToString().Substring(0, 10);
            }
}

И функция создания подписи с помощью алгоритма хэширования HMAC-SHA256, которая будет использоваться в программе:

private static string getHMACSHA256(string key, string message)
        {
            byte[] byte_key = Encoding.UTF8.GetBytes(key);
            byte[] byte_message = Encoding.UTF8.GetBytes(message);

            HMACSHA256 hash = new HMACSHA256(byte_key);
            byte[] hash_message = hash.ComputeHash(byte_message);

            return Convert.ToBase64String(hash_message);
        }

Создание подписи

Процесс создания строки подписи весьма специфичен, а именно:

  1. Строка должна начинаться с наименования HTTP метода в верхнем регистре, т.е. GET;
  2. Далее добавляется символ & (амперсанд);
  3. Преобразуем строку с URL адресом в её escape-представление;
  4. Затем снова добавляем символ & (амперсанд);
  5. И, наконец, преобразуем строку передаваемых параметров в её escape-представление.

Следуя данной инструкции должна получится вот такая строка кода:

string base_request_uri = "GET" + "&" + Uri.EscapeDataString(endpoint) + "&";

Далее формируем параметры для передачи в запросе по следующей схеме:

  • Необходимо преобразовать все ключи и значения параметров в escape-представление(или ещё говорят URL-кодирование);
  • Отсортировать по алфавиту ключи параметров;
  • Для каждой пары ключ/значение, нужно:
      • добавить в конец строки преобразованный в escape(или URL-кодирование) ключ(имя параметра);
      • добавить в конец строки знак «=»;
      • добавить в конец строки преобразованное в escape-значение параметр;
      • при наличии ещё одной пары ключ/значение, добавляем в конец строки амперсанд(&).

Теперь посмотрим как это выглядит на практике:

//Объявляем переменную для создания строки параметров
string stringToSign = string.Empty;

foreach (var param in dic.OrderBy(x => x.Key))
  stringToSign += Uri.EscapeDataString(param.Key) + "=" + Uri.EscapeDataString(param.Value) + "&";

base_request_uri = base_request_uri + Uri.EscapeDataString(stringToSign.TrimEnd('&'));

Далее добавляем параметр подписи:

dic.Add("oauth_signature", getHMACSHA256(wc_secret, base_request_uri));

Почти все готово, теперь осталось объединить все полученные нами параметры в одну строку для передачи данных в запросе:

string parmstr = string.Empty;

foreach (var param in dic)
  parmstr += param.Key + "=" + Uri.EscapeDataString(param.Value) + "&";

string result = "?" + parmstr.TrimEnd('&');

И выполнить сам запрос:

HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(endpoint + result);
httpWebRequest.Method = "GET";
httpWebRequest.AllowReadStreamBuffering = false;

WebResponse webResponse = await httpWebRequest.GetResponseAsync().ConfigureAwait(false);

Stream webStream = webResponse.GetResponseStream();
// Полученный ответ будем считывать побайтно преобразовывая в UTF8 и добавляя в строку sb
StringBuilder sb = new StringBuilder();
byte[] Buffer = new byte[512];
int count = 0;
count = await webStream.ReadAsync(Buffer, 0, Buffer.Length).ConfigureAwait(false);
while (count > 0)
   {
      sb.Append(Encoding.UTF8.GetString(Buffer, 0, count));
      count = await webStream.ReadAsync(Buffer, 0, Buffer.Length).ConfigureAwait(false);
   }

REST API предоставляет ответ в JSON формате, поэтому десериализуем полученную строку в ранее описанный класс Product:

var products = JsonConvert.DeserializeObject<List<MyProduct>>(sb.ToString());

foreach(var product in products)
{
   // Выводим список полученных товаров в консоле
   Console.WriteLine("id = " + product.id + ", name = " + product.name + ", slug = " + product.slug);
}

Заметьте, что мы передали REST API только обязательные параметры аутентификации, поэтому по умолчанию мы получили 10 товаров. Для того чтобы получить, например 20 товаров, нужно также передать параметр per_page, т.е. конечная точка будет /products?per_page=15.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *