delivengo
Forum Replies Created
-
Bonjour,
Pouvez-vous modifier le fichier wp-content/plugins/delivengo/src/Services/Api/ApiPayload.php et remplacer vers la ligne 315 :
$price = $item->get_subtotal();Par :
$price = $item->get_subtotal() / $quantity;Ça devrait résoudre le problème pour les étiquettes générées automatiquement ou depuis le listing des commandes.
Nous allons inclure cette modification dans la prochaine version, merci d’avoir remonté le souci.
Forum: Plugins
In reply to: [Delivengo: Shipping methods for WooCommerce] delivengo pour woocommerceNous n’avons pas d’autre plugin pour lettre suivie.
Ce plugin ajoute ces méthodes si vous avez souscrit à un contrat Delivengo profil :
- Delivengo Suivi
- Delivengo Avec accusé de réception
- Delivengo Sans accusé de réception
- Delivengo Économique
- Delivengo Prioritaire
Si vous avez souscrit à un contrat Delivengo Easy, il n’y aura qu’une méthode de livraison disponible.
Dans les deux cas, il me semble que ces méthodes correspondent à la livraison d’un colis (impression d’une étiquette de livraison).
Notez que dans WooCommerce, vous pouvez ajouter une méthode de livraison personnalisée et la nommer comme vous le souhaitez.
Forum: Plugins
In reply to: [Delivengo: Shipping methods for WooCommerce] delivengo pour woocommerceBonjour,
Ce plugin ajoute des méthodes de livraison Delivengo, que vous pouvez ajouter à vos zones.
Vous pouvez donc très bien proposer plusieurs méthodes de livraison sur la même zone (Delivengo + lettre suivie).Si vous souhaitez ne proposer qu’une méthode de livraison à vos clients, et décider après-coup quel transporteur choisir, je suppose que vous pouvez ne montrer que l’envoi via Delivengo (et renommer la méthode si besoin). Vous pourrez alors générer les étiquettes sur certaines commandes en particulier depuis le listing des commandes.
Nous ne gérons que l’extension WordPress, pour les soucis sur le site Delivengo il faudra les contacter directement.
Vous pouvez essayer de vider le champ du nom pour l’adresse dans les réglages (n’avoir que la raison sociale).
Si ça ne marche pas, pouvez-vous contacter un conseiller Delivengo afin d’obtenir le lien de la documentation pour leur API ? Les messages d’erreur devraient être décrits dedans, ce qui m’aidera à identifier d’où vient le souci.
Bonjour,
Les adresses paramétrées sur votre compte Delivengo sont affichées en haut de cette section dans les réglages, mais est-ce que les champs qui se trouve en-dessous sont bien remplis ?
Si ce n’est pas le cas, vous pouvez cliquer sur l’une des adresses en haut de page pour pré-remplir les champs.
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.
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;
}
}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.jset 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\"}"Forum: Plugins
In reply to: [Delivengo: Shipping methods for WooCommerce] Sous compte DelivengoBonjour,
Merci pour votre message.
Je vois que votre demande a été transférée à notre équipe et qu’un rendez-vous a bien été organisé. Nous pourrons ainsi traiter ensemble de vos différentes problématiques pour vous accompagner au mieux.
Merci.
Je reste à votre disposition.
Bonne journée.
L’équipe DelivengoBonjour et désolé pour ce long délais, nous ne recevions pas les notifications du forum WP.
Pour la marge lors de l’impression, elle peut être causée par l’option “scale”. Vous pouvez essayer de passer à “Fit to printable area” par défaut pour éviter ce problème :

J’ai préparé une modification pour la prochaine version afin d’ajouter un bouton de téléchargement et un bouton d’impression de l’étiquette sur la page de la commande 👍
Bonne journée
Forum: Plugins
In reply to: [Delivengo: Shipping methods for WooCommerce] Erreur génération étiquettes..Bonjour et désolé pour le délais,
Pour la génération d’une étiquette, l’extension va prendre l’adresse et le numéro du store dans les réglages Delivengo, onglet “Mes adresses”.
Pour le destinataire, l’extension va prendre l’adresse de livraison et le téléphone de facturation (ça c’est une erreur, il devrait prendre le téléphone de livraison en priorité).
Est-ce que toutes ces infos sont bien renseignées ?
Bonne journée