• Resolved nathan62223

    (@nathan62223)


    Bonjour,

    Lorsque j’essaye de valider la clé API, j’ai le message suivant : JSON.parse: unexpected character at line 1 column 1 of the JSON data

    Version WordPress : 5.5.15

    PHP Version 7.4.18

    Merci,

Viewing 6 replies - 1 through 6 (of 6 total)
  • Plugin Author delivengo

    (@delivengo)

    Bonjour,

    Pouvez-vous appuyer sur F12 et vérifier la réponse de l’appel dans l’onglet “Réseau” lorsque vous essayez d’ajouter votre clé API ?

    Normalement une nouvelle ligne devrait s’ajouter lorsque vous cliquez sur le bouton, si vous cliquez dessus, vous pourrez voir le résultat de l’appel.

    Généralement quand une erreur comme ?a arrive, c’est qu’un message d’erreur est affiché sur toutes les pages et “casse” le format attendu lors d’un appel ajax.

    Si vous ne trouvez pas plus d’informations, vous pouvez aussi modifier le fichier :

    wp-content/plugins/delivengo/assets/js/global/ajax.js

    et ajouter ce code vers la ligne 13 :

    console.log(response.text());

    Comme ceci :

    const mdAjaxHelper = {
    post: (data) => {
    const formData = new FormData();

    for (const key in data) {
    formData.append(key, data[key]);
    }

    return fetch(ajaxurl, {
    body: formData,
    method: 'POST'
    }).then(response => {
    console.log(response.text());
    if (!response.ok) {
    return Promise.reject(response);
    }
    return response.json();
    }).catch(response => response.json().then(error => Promise.reject(error)));
    }
    };

    Une fois fait, rafra?chissez le cache navigateur avec cmd+maj+R ou ctrl+F5, appuyez sur F12 puis ouvrez l’onglet “Console”. Essayez d’ajouter votre clé API, un message nommé “Promise” devrait apparaitre dans la console. Pouvez-vous m’en copier coller le contenu lorsqu’il est déplié ?

    Voici un exemple de message :

    Promise {<pending>}
    [[Prototype]]: Promise
    [[PromiseState]]: "fulfilled"
    [[PromiseResult]]: "{\"status\":\"success\",\"message\":\"This API key is valid\"}"
    Thread Starter nathan62223

    (@nathan62223)

    Bonjour,

    Merci pour votre retour, voici ce que j’ai comme réponse :

    Promise { <state>: "pending" }
    ?
    <state>: "fulfilled"
    ?
    <value>: '<p>une erreur critique est survenue sur votre site.</p><p><a href="https://fr.www.ads-software.com/support/article/debugging-in-wordpress/">En apprendre plus sur le débogage de WordPress.</a></p>'

    Et voici ce que j’ai dans le log WP :

    [15-Oct-2024 15:02:45 UTC] PHP Fatal error:  Uncaught Error: Class 'WpOrg\Requests\Requests' not found in /var/www/website/wp-content/plugins/delivengo/src/Services/Api/Api.php:49
    Stack trace:
    #0 /var/www/website/wp-content/plugins/delivengo/src/Services/Api/Api.php(92): Delivengo\Services\Api\Api->callApi()
    #1 /var/www/website/wp-content/plugins/delivengo/src/Controllers/Settings/Account.php(29): Delivengo\Services\Api\Api->getAccount()
    #2 /var/www/website/wp-includes/class-wp-hook.php(287): Delivengo\Controllers\Settings\Account->testApiKey()
    #3 /var/www/website/wp-includes/class-wp-hook.php(311): WP_Hook->apply_filters()
    #4 /var/www/website/wp-includes/plugin.php(478): WP_Hook->do_action()
    #5 /var/www/website/wp-admin/admin-ajax.php(176): do_action()
    #6 {main}

    Merci.

    • This reply was modified 4 months, 2 weeks ago by nathan62223.
    Plugin Author delivengo

    (@delivengo)

    J’ai préparé une modification pour la prochaine version afin de remplacer l’utilisation de la librairie Requests de WordPress par un appel curl simple.

    En attendant la mise en ligne, vous pouvez modifier le fichier wp-content/plugins/delivengo/src/Services/Api/Api.php et remplacer son contenu par :

    <?php

    namespace Delivengo\Services\Api;

    use Delivengo\Classes\Label\LabelQueries;
    use Delivengo\Helpers\Logger;
    use Delivengo\Helpers\Request;
    use Delivengo\Services\Core\MergePdf;
    use Delivengo\Services\WooCommerce\Settings;

    class Api
    {
    const URL_BASE = 'https://mydelivengo.laposte.fr/api/v2.4';

    public string $apiKey;
    private array $headers = [];

    public function __construct(string $apiKey = '')
    {
    if ($apiKey) {
    $this->apiKey = $apiKey;
    } else {
    $this->apiKey = get_option('md_api_key', '');
    }
    }

    protected function addHeader($key, $value): void
    {
    if (empty($key) || empty($value)) {
    return;
    }

    $this->headers[$key] = $value;
    }

    /**
    * @throws \Exception
    */
    protected function callApi(string $method, string $endpoint, array $data = []): array
    {
    $url = self::URL_BASE.$endpoint;

    $this->addHeader('API-Authorization', $this->apiKey);
    $this->addHeader('User-Agent', 'PHP/'.phpversion());

    if ('POST' === $method) {
    $this->addHeader('Content-Type', 'application/json');
    }

    $data['cms'] = 'wordpress';

    $options = [
    'verifySsl' => false,
    'headers' => $this->headers,
    'method' => $method,
    'data' => $data,
    ];

    try {
    $response = Request::curl($url, $options);
    } catch (\Exception $exception) {
    Logger::error('Could not call Delivengo API', ['message' => $exception->getMessage()]);

    throw new \Exception(sprintf(__('Could not call Delivengo API: %s', 'wc_delivengo'), $exception->getMessage()));
    }

    if ($response['status_code'] < 200 || $response['status_code'] > 299) {
    Logger::error(
    'Error responded from Delivengo API',
    [
    'status_code' => $response['status_code'],
    'body' => $response,
    'dataSent' => $data,
    ]
    );

    if ($response['status_code'] == 401) {
    throw new \Exception(__('Invalid API key', 'wc_delivengo'));
    }

    if (!empty($response['curl_error'])) {
    throw new \Exception($response['curl_error']);
    }

    if (!empty($response['error']['details'])) {
    $errorMessages = $this->getErrorMessages($response['error']['details']);
    throw new \Exception(trim($response['error']['description'], '.').' : '.$errorMessages);
    }

    if (!empty($response['error']['description'])) {
    throw new \Exception(sprintf(__('Error responded from Delivengo API with the message: %s', 'wc_delivengo'), $response['error']['description']));
    }

    throw new \Exception(sprintf(__('Error responded from Delivengo API with status code %s', 'wc_delivengo'), $response['status_code']));
    }

    return $response;
    }

    /**
    * @throws \Exception
    */
    public function getAccount(): array
    {
    return $this->callApi('GET', '/utilisateurs/0');
    }

    /**
    * @throws \Exception
    */
    public function updateAccountExtra($extra): array
    {
    return $this->callApi('PUT', '/utilisateurs/0', ['data' => ['extra' => $extra]]);
    }

    /**
    * @throws \Exception
    */
    public function getAddresses(): array
    {
    return $this->callApi('GET', '/expediteurs');
    }

    /**
    * @throws \Exception
    */
    public function createShipment(array $orders, array $customParams = []): array
    {
    try {
    $labelQueries = new LabelQueries();
    foreach ($orders as $key => $order) {
    $existingLabel = $labelQueries->getLabelByOrderId($order->get_id());
    if (!empty($existingLabel)) {
    unset($orders[$key]);
    }
    }

    if (empty($orders)) {
    throw new \Exception(__('No order to create shipment', 'wc_delivengo'));
    }

    $accountType = get_option(Settings::ACCOUNT_TYPE_OPTION, '');
    if (empty($accountType)) {
    Logger::error(__('Account type unknown, make sure to enter your API key in the settings', 'wc_delivengo'));
    throw new \Exception(__('Account type unknown, make sure to enter your API key in the settings', 'wc_delivengo'));
    }

    $payloadService = new ApiPayload($orders);
    $payloadService
    ->withContract($orders, $accountType)
    ->withExtra($accountType)
    ->withReceiver($orders)
    ->withSender()
    ->withWeight($orders, $customParams)
    ->withCustomsDocuments($orders, $customParams)
    ->withParametersSend($orders, $accountType);

    $this->addHeader('Accept', 'application/pdf');

    $shipment = $this->callApi('POST', '/envois?'.$payloadService->getParametersUrl(), ['data' => $payloadService->payload]);

    $labels = [];

    foreach ($orders as $key => $order) {
    $label = [
    'label' => $shipment['data']['documents_supports'],
    'creation_date' => date('Y-m-d H:i:s'),
    'order_id' => $order->get_id(),
    'tracking_number' => $shipment['data']['plis'][$key]['numero'],
    'label_id' => $shipment['data']['plis'][$key]['id'],
    'sending_id' => $shipment['data']['id'],
    ];

    if (!empty($shipment['data']['documents_douaniers'])) {
    $label['label'] = (new MergePdf())->mergeBlobPdf([$shipment['data']['documents_supports'], $shipment['data']['documents_douaniers']]);
    }

    $label['id'] = $labelQueries->create($label);
    $labels[] = $label;
    }

    delete_option('md_label_error_'.$order->get_id());
    } catch (\Exception $exception) {
    update_option('md_label_error_'.$order->get_id(), $exception->getMessage());

    throw $exception;
    }

    return $labels;
    }

    /**
    * @throws \Exception
    */
    public function getLabelTrackingUrl(object $label): ?string
    {
    if (!empty($label->tracking_url)) {
    return $label->tracking_url;
    }

    $labelDetails = $this->callApi('GET', '/plis/'.$label->label_id);
    if (empty($labelDetails['data']['tracking']['url'])) {
    return false;
    }

    LabelQueries::setTrackingUrl($label, $labelDetails['data']['tracking']['url']);

    return $labelDetails['data']['tracking']['url'];
    }

    /**
    * @throws \Exception
    */
    public function getLabelStatus(object $label): array
    {
    $labelDetails = $this->callApi('GET', '/plis/'.$label->label_id);

    if (empty($labelDetails['data']['statut'])) {
    throw new \Exception(__('Could not retrieve the parcel status', 'wc_delivengo'));
    }

    if (!empty($labelDetails['data']['statut']['libelle']) && $labelDetails['data']['statut']['libelle'] === 'Non suivi') {
    $labelDetails['data']['statut']['id'] = -1;
    }

    return $labelDetails['data']['statut'];
    }

    private function getErrorMessages(array $details, string $name = ''): string
    {
    $messages = '';
    foreach ($details as $key => $oneDetail) {
    if (is_array($oneDetail)) {
    $messages .= $this->getErrorMessages($oneDetail, $key);
    } else {
    $fieldName = ucfirst(str_replace('_', ' ', $name));
    $messages .= "\n".$fieldName.' : '.trim($oneDetail, '.');
    }
    }

    return $messages;
    }

    public function addWebhook(array $data): bool
    {
    try {
    $this->callApi('POST', '/webhooks', $data);

    return true;
    } catch (\Exception $exception) {
    Logger::error('Could not add webhook', ['message' => $exception->getMessage()]);

    return false;
    }
    }
    }

    puis modifier le fichier wp-content/plugins/delivengo/src/Helpers/Request.php et remplacer son contenu par :

    <?php

    namespace Delivengo\Helpers;

    class Request
    {
    public static function getVar(string $type, string $name, $default = '', string $source = 'REQUEST')
    {
    $source = strtoupper($source);

    switch ($source) {
    case 'GET':
    $input = &$_GET;
    break;
    case 'POST':
    $input = &$_POST;
    break;
    case 'FILES':
    $input = &$_FILES;
    break;
    case 'COOKIE':
    $input = &$_COOKIE;
    break;
    case 'ENV':
    $input = &$_ENV;
    break;
    case 'SERVER':
    $input = &$_SERVER;
    break;
    default:
    $source = 'REQUEST';
    $input = &$_REQUEST;
    break;
    }

    if (!isset($input[$name])) {
    return $default;
    }

    $result = $input[$name];
    unset($input);
    if ($type === 'array') {
    $result = (array)$result;
    }

    if (in_array($source, ['POST', 'REQUEST', 'GET', 'COOKIE'])) {
    $result = wp_unslash($result);
    }

    if (is_array($result)) {
    return $result;
    }

    switch ($type) {
    case 'string':
    $result = (string)$result;
    break;
    case 'int':
    $result = (int)$result;
    break;
    case 'float':
    $result = (float)$result;
    break;
    case 'bool':
    $result = (bool)$result;
    break;
    case 'word':
    $result = preg_replace('#[^a-zA-Z_]#', '', $result);
    break;
    case 'cmd':
    $result = preg_replace('#[^a-zA-Z0-9_\.-]#', '', $result);
    $result = ltrim($result, '.');
    break;
    default:
    break;
    }

    if (!is_string($result)) {
    return $result;
    }

    $result = trim($result);

    if (!preg_match('//u', $result)) {
    // String contains invalid byte sequence, remove it
    $result = htmlspecialchars_decode(htmlspecialchars($result, ENT_IGNORE, 'UTF-8'));
    }

    return $result;
    }

    public static function endAjax($success = true, $data = [])
    {
    echo json_encode(
    [
    'type' => $success ? 'success' : 'error',
    'data' => $data,
    ]
    );
    exit;
    }

    /**
    * @param string $url
    * @param array $options
    * - verifySsl: boolean, default true
    * - headers: array for example ['Content-Type' => 'application/json']
    * - data: array, if Content-Type is application/json, the data will be json_encoded otherwise it will be urlencoded
    * - dns: string
    * - proxy: array ['host' => '127.0.0.1:8888', 'auth' => 'user:password'] the auth is optional
    * - method: string GET, POST, etc
    *
    * @return array
    */
    public static function curl(string $url, array $options = []): array
    {
    $options['verifySsl'] = $options['verifySsl'] ?? true;

    $headers = [];
    if (!empty($options['headers']) && is_array($options['headers'])) {
    $headers = $options['headers'];
    }

    $data = [];
    if (!empty($options['data']) && is_array($options['data'])) {
    $data = $options['data'];
    }

    $allowedMethods = ['GET', 'POST'];
    $method = 'GET';
    if (!empty($options['method']) && in_array($options['method'], $allowedMethods)) {
    $method = $options['method'];
    }

    $dataFormatted = '';
    if (!empty($data)) {
    $isHeaderContentTypeJson = !empty($headers['Content-Type']) && $headers['Content-Type'] === 'application/json';
    if ($method === 'POST' && $isHeaderContentTypeJson) {
    $dataFormatted = json_encode($data);
    } else {
    $dataFormatted = http_build_query($data);
    }
    }

    if ($method === 'GET') {
    $url .= (strpos($url, '?') === false ? '?' : '&').$dataFormatted;
    }

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    if ($method === 'POST') {
    curl_setopt($ch, CURLOPT_POST, true);
    if (!empty($data)) {
    curl_setopt($ch, CURLOPT_POSTFIELDS, $dataFormatted);
    }
    }

    if (!$options['verifySsl']) {
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    }

    if (!empty($headers)) {
    // We have headers like this ['Content-Type' => 'application/json']
    // We need headers like this ['Content-Type: application/json']
    $headersFormatted = array_map(
    function ($key, $value) {
    return $key.': '.$value;
    },
    array_keys($headers),
    $headers
    );
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headersFormatted);
    }

    $result = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if (curl_errno($ch)) {
    $error = curl_error($ch);

    curl_close($ch);

    return [
    'curl_error' => $error,
    'status_code' => $httpCode,
    ];
    }

    curl_close($ch);

    $result = json_decode($result, true);
    $result['status_code'] = $httpCode;

    return $result;
    }
    }
    Thread Starter nathan62223

    (@nathan62223)

    Parfait ?a fonctionne !

    J’ai une autre erreur (plus critique) avec le plugin, lorsque je consulte une commande :

    Fatal error: Uncaught Automattic\WooCommerce\Vendor\League\Container\Exception\NotFoundException: Alias (Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController) is not being managed by the container or delegates in /var/www/site-web.com/wp-content/plugins/woocommerce/vendor/league/container/src/Container.php:188 Stack trace: #0 /var/www/site-web.com/wp-content/plugins/woocommerce/src/Internal/DependencyManagement/ExtendedContainer.php(116): Automattic\WooCommerce\Vendor\League\Container\Container->get() #1 /var/www/site-web.com/wp-content/plugins/woocommerce/src/Container.php(72): Automattic\WooCommerce\Internal\DependencyManagement\ExtendedContainer->get() #2 /var/www/site-web.com/wp-content/plugins/delivengo/src/Services/WooCommerce/Orders.php(108): Automattic\WooCommerce\Container->get() #3 /var/www/site-web.com/wp-includes/class-wp-hook.php(289): Delivengo\Services\WooCommerce\Orders->addMetaBox() #4 /var/www/site-web.com/wp-includes/class-wp-hook.php(311): WP_Hook->apply_filters() #5 /var/www/site in /var/www/site-web.com/wp-content/plugins/woocommerce/vendor/league/container/src/Container.php on line 188

    Merci

    Plugin Author delivengo

    (@delivengo)

    Cette erreur peut arriver sur les vieilles versions de WooCommerce, avant que le HPOS soit ajouté.

    Vous pouvez modifier le fichier wp-content/plugins/delivengo/src/Services/WooCommerce/Orders.php et remplacer les lignes 108 à 110 :

    $screenId = wc_get_container()->get(CustomOrdersTableController::class)->custom_orders_table_usage_is_enabled()
    ? wc_get_page_screen_id('shop-order')
    : 'shop_order';

    par :

    $screenId = class_exists('Automattic\\WooCommerce\\Internal\\DataStores\\Orders\\CustomOrdersTableController') && wc_get_container()
    ->get(Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class)
    ->custom_orders_table_usage_is_enabled()
    ? wc_get_page_screen_id('shop-order')
    : 'shop_order';

    ?a vérifiera que la classe de WooCommerce que nous utilisons existe bien.

    Thread Starter nathan62223

    (@nathan62223)

    Parfait, tout semble bon, merci !

Viewing 6 replies - 1 through 6 (of 6 total)
  • You must be logged in to reply to this topic.