API QuickBooks возвращает 401 с действующим токеном, но только при обновлении/создании.

Вопрос или проблема

Я пытаюсь написать приложение для интеграции с API QuickBooks, но каждый раз, когда я пытаюсь создать или обновить объект в Sandbox, я получаю 401 для корректного токена доступа. Я написал тестовую функцию, которая демонстрирует проблему:

async testUpdateQB(accessToken: string, realmId: string) {
    const bearer = `Bearer ${accessToken}`;
    const url = `https://sandbox-quickbooks.api.intuit.com/v3/company/${realmId}/customer/1?minorversion=73`;

    const headers = {
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json;charset=UTF-8',
        Authorization: bearer,
      },
    };

    let customer1;
    try {
      customer1 = await axios.get(url, headers);

      console.log(`Вызов 1 Название: ${customer1.data.Customer.DisplayName}`);
    } catch (exception: AxiosError | any) {
      console.log(`Вызов 1 Не удался: ${JSON.stringify(exception.response.data)}`);
    }

    if (!customer1) {
      console.log('ОШИБКА: Клиент не найден!');
      return;
    }

    try {
      const update = {
        DisplayName: 'Обновлено!',
        SyncToken: customer1.data.Customer.SyncToken,
        Id: customer1.data.Customer.Id,
        sparse: true,
      };

      const response = await axios.post(url, {
        ...headers,
        body: update,
      });

      console.log(`Вызов 2 Ответ: ${JSON.stringify(response.data)}`);
    } catch (exception: AxiosError | any) {
      console.log(`Вызов 2 не удался: ${JSON.stringify(exception.response.data)}`);
    }

    try {
      const customer2 = await axios.get(url, headers);

      console.log(`Вызов 3 Название: ${customer2.data.Customer.DisplayName}`);
    } catch (exception: AxiosError | any) {
      console.log(`Вызов 3 Не удался: ${JSON.stringify(exception.response.data)}`);
    }
  }

Вот вывод:

Вызов 1 Название: Убежище для птиц Эми - тест

Вызов 2 не удался: {"warnings":null,"intuitObject":null,"fault":{"error":[{"message":"message=AuthenticationFailed; errorCode=003200; statusCode=401","detail":"","code":"3200","element":null}],"type":"AUTHENTICATION"},"report":null,"queryResponse":null,"batchItemResponse":[],"attachableResponse":[],"syncErrorResponse":null,"requestId":null,"time":1731438279628,"status":null,"cdcresponse":[]}

Вызов 3 Название: Убежище для птиц Эми - тест

Как видно, в трех вызовах используются идентичные заголовки, включая токен доступа. Первый и третий вызовы (оба читают клиента) проходят успешно, но второй вызов завершается с 401. Как может второй вызов завершиться с 401, если третий вызов проходит успешно при использовании идентичного токена доступа?

Ответ или решение

Причина ошибки 401 при обновлении/создании объектов в QuickBooks API

Ошибка 401 "Unauthorized" в ответ на запросы к QuickBooks API, при этом вы получаете действительный токен доступа, может быть довольно запутанной. Вы привели достаточно информации, чтобы проанализировать ситуацию подробно. Ниже раскрываются возможные причины ошибки и предложены пути её решения.

Анализ предоставленного кода

Ваш код выполняет три HTTP-запроса к QuickBooks API:

  1. Получение информации о клиенте (HTTP GET).
  2. Обновление информации о клиенте (HTTP POST).
  3. Снова получение информации о клиенте (HTTP GET).

Первый и третий запросы выполняются успешно с использованием одного и того же токена доступа, тогда как второй запрос возвращает ошибку 401. Это ведёт к необходимости рассмотреть некоторые аспекты.

Возможные причины ошибки 401

  1. Метод HTTP:

    • Вы используете axios.post для обновления информации, но QuickBooks API ожидает, что для обновлений будет использоваться метод PUT. Убедитесь, что вы используете правильный метод для выполнения обновления.
    • Исправьте строку, чтобы использовать axios.put вместо axios.post.
  2. Правильность заголовков:

    • В текущем запросе в axios.post неверно передавается объект headers. Вместо того чтобы передавать headers в ...headers, они должны быть просто добавлены непосредственно в запрос. Обратите внимание на то, как заголовки передаются в запросах:
      const response = await axios.put(url, update, headers);
  3. Содержимое тела запроса:

    • Каждый раз, когда данные отправляются на сервер, они должны быть правильно структурированы. В коде body: update не должно быть, так как объект update уже передаётся в теле.
    • После перехода на правильный метод нужно будет просто передать update как тело запроса.
  4. SyncToken:

    • Убедитесь, что вы передаете актуальный SyncToken для обновляемого объекта. Это значение может изменяться после любого изменения информации о клиенте. Если это значение недействительно (например, устарело с момента последнего получения), ответ тоже будет 401.
  5. Токен доступа:

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

Пример исправленного кода

Основываясь на вышеуказанных моментах, вот как может выглядеть исправленный участок кода:

try {
  const update = {
    DisplayName: 'Updated!',
    SyncToken: customer1.data.Customer.SyncToken,
    Id: customer1.data.Customer.Id,
    sparse: true,
  };

  const response = await axios.put(url, update, headers);

  console.log(`Call 2 Response: ${JSON.stringify(response.data)}`);
} catch (exception: AxiosError | any) {
  console.log(`Call 2 failed: ${JSON.stringify(exception.response.data)}`);
}

Заключение

Ошибки 401 при работе с API часто возникают из-за неправильно выбранного HTTP метода или проблемы с токенами. Проверьте эти аспекты, а также убедитесь в актуальности данных, отправляемых в запросе. Если после всех проверок проблема остаётся, возможно, стоит обратиться в поддержку QuickBooks для более глубокого анализа проблемы.

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

Капча загружается...